1 /*
2 * Copyright (c) 2011 - 2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kmem.h>
31 #include <sys/proc.h>
32 #include <sys/lock.h>
33 #include <sys/socket.h>
34 #include <sys/uio.h>
35 #include <sys/random.h>
36 #include <sys/note.h>
37 #include <sys/errno.h>
38 #include <sys/cmn_err.h>
39
40 #include <smb/ntaccess.h>
41 #include <smb/winioctl.h>
42
43 #include <netsmb/smb_osdep.h>
44
45 #include <netsmb/smb.h>
46 #include <netsmb/smb2.h>
47 #include <netsmb/smb_conn.h>
48 #include <netsmb/smb_subr.h>
49 #include <netsmb/smb_tran.h>
50 #include <netsmb/smb_rq.h>
51 #include <netsmb/smb2_rq.h>
52
53 /*
54 * Supported dialects. Keep sorted by number because of how the
55 * vc_maxver check below may truncate this list.
56 */
57 #define NDIALECTS 3
58 static const uint16_t smb2_dialects[NDIALECTS] = {
59 SMB2_DIALECT_0210,
60 SMB2_DIALECT_0300,
61 SMB2_DIALECT_0302,
62 };
63
64 /* Optional capabilities we advertise (none yet). */
65 uint32_t smb2_clnt_caps = 0;
66
67 /* How many credits to ask for during ssn. setup. */
68 uint16_t smb2_ss_req_credits = 64;
69
70 /*
71 * Default timeout values, all in seconds.
72 * Make these tunable (only via mdb for now).
73 */
74 int smb2_timo_notice = 15;
75 int smb2_timo_default = 30;
76 int smb2_timo_logon = 45;
77 int smb2_timo_open = 45;
78 int smb2_timo_read = 45;
79 int smb2_timo_write = 60;
80 int smb2_timo_append = 90;
81
82 /*
83 * This is a special handler for the odd SMB1-to-SMB2 negotiate
84 * response, where an SMB1 request gets an SMB2 response.
85 *
86 * Unlike most parse functions here, this needs to parse both
87 * the SMB2 header and the nego. response body. Note that
88 * the only "SMB2" dialect our SMB1 negotiate offered was
89 * { SMB_DIALECT_SMB2_FF, "SMB 2.???"} so the only valid
90 * SMB2 dialect we should get is: SMB2_DIALECT_02ff
91 */
92 int
smb2_parse_smb1nego_resp(struct smb_rq * rqp)93 smb2_parse_smb1nego_resp(struct smb_rq *rqp)
94 {
95 struct smb_vc *vcp = rqp->sr_vc;
96 struct smb_sopt *sp = &vcp->vc_sopt;
97 struct mdchain *mdp;
98 uint16_t length = 0;
99 int error;
100
101 /* Get pointer to response data */
102 smb_rq_getreply(rqp, &mdp);
103
104 error = smb2_rq_parsehdr(rqp);
105 if (error != 0)
106 return (error);
107
108 /*
109 * Parse SMB 2/3 Negotiate Response
110 * We are already pointing to begining of Response data
111 */
112
113 /* Check structure size is 65 */
114 md_get_uint16le(mdp, &length);
115 if (length != 65)
116 return (EBADRPC);
117
118 /* Get Security Mode */
119 md_get_uint16le(mdp, &sp->sv2_security_mode);
120
121 /* Get Dialect. */
122 error = md_get_uint16le(mdp, &sp->sv_proto);
123 if (error != 0)
124 return (error);
125
126 /* What dialect did we get? */
127 if (sp->sv_proto != SMB2_DIALECT_02ff) {
128 SMBERROR("Unknown dialect 0x%x\n", sp->sv_proto);
129 return (EINVAL);
130 }
131 /* Set our (internal) SMB1 dialect also. */
132 sp->sv_proto = SMB_DIALECT_SMB2_FF;
133
134 /*
135 * This request did not go through smb2_iod_addrq and
136 * smb2_iod_process() so the SMB2 message ID state is
137 * behind what we need it to be. Fix that.
138 */
139 vcp->vc2_next_message_id = 1;
140 vcp->vc2_limit_message_id = 2;
141
142 /*
143 * Skip parsing the rest. We'll get a normal
144 * SMB2 negotiate next and do negotiate then.
145 */
146 return (0);
147 }
148
149 int
smb2_smb_negotiate(struct smb_vc * vcp,struct smb_cred * scred)150 smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
151 {
152 smb_sopt_t *sp = &vcp->vc_sopt;
153 smbioc_ssn_work_t *wk = &vcp->vc_work;
154 struct smb_rq *rqp = NULL;
155 struct mbchain *mbp = NULL;
156 struct mdchain *mdp = NULL;
157 uint16_t *ndialects_p;
158 uint16_t ndialects = NDIALECTS;
159 boolean_t will_sign = B_FALSE;
160 uint16_t length = 0;
161 uint16_t security_mode;
162 uint16_t sec_buf_off;
163 uint16_t sec_buf_len;
164 int err, i;
165
166 /*
167 * Compute security mode
168 */
169 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
170 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
171 } else {
172 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
173 }
174
175 err = smb_rq_alloc(VCTOCP(vcp), SMB2_NEGOTIATE, scred, &rqp);
176 if (err)
177 return (err);
178
179 /*
180 * Build the SMB2 negotiate request.
181 */
182 smb_rq_getrequest(rqp, &mbp);
183 mb_put_uint16le(mbp, 36); /* Struct Size */
184 ndialects_p = mb_reserve(mbp, 2); /* Dialect Count */
185 mb_put_uint16le(mbp, security_mode);
186 mb_put_uint16le(mbp, 0); /* Reserved */
187 mb_put_uint32le(mbp, smb2_clnt_caps);
188 mb_put_mem(mbp, vcp->vc_cl_guid, 16, MB_MSYSTEM);
189 mb_put_uint64le(mbp, 0); /* Start Time */
190 for (i = 0; i < ndialects; i++) { /* Dialects */
191 if (smb2_dialects[i] > vcp->vc_maxver)
192 break;
193 mb_put_uint16le(mbp, smb2_dialects[i]);
194 }
195 *ndialects_p = htoles(i);
196
197 /*
198 * Do the OTW call.
199 */
200 err = smb2_rq_internal(rqp, smb2_timo_default);
201 if (err) {
202 goto errout;
203 }
204 /* Should only get status success. */
205 if (rqp->sr_error != NT_STATUS_SUCCESS) {
206 err = ENOTSUP;
207 goto errout;
208 }
209
210 /*
211 * Decode the negotiate response
212 */
213 smb_rq_getreply(rqp, &mdp);
214
215 md_get_uint16le(mdp, &length); /* Struct size */
216 if (length != 65) {
217 err = EBADRPC;
218 goto errout;
219 }
220
221 md_get_uint16le(mdp, &sp->sv2_security_mode);
222 md_get_uint16le(mdp, &sp->sv_proto); /* dialect */
223 md_get_uint16le(mdp, NULL); /* reserved */
224 md_get_mem(mdp, sp->sv2_guid, 16, MB_MSYSTEM);
225 md_get_uint32le(mdp, &sp->sv2_capabilities);
226 md_get_uint32le(mdp, &sp->sv2_maxtransact);
227 md_get_uint32le(mdp, &sp->sv2_maxread);
228 md_get_uint32le(mdp, &sp->sv2_maxwrite);
229 md_get_uint64le(mdp, NULL); /* curr_time */
230 md_get_uint64le(mdp, NULL); /* boot_time */
231
232 /* Get Security Blob offset and length */
233 md_get_uint16le(mdp, &sec_buf_off);
234 err = md_get_uint16le(mdp, &sec_buf_len);
235 if (err != 0)
236 goto errout;
237 md_get_uint32le(mdp, NULL); /* reserved */
238
239 /*
240 * Security buffer offset is from the beginning of SMB 2 Header
241 * Calculate how much further we have to go to get to it.
242 * Current offset is: SMB2_HDRLEN + 64
243 */
244 if (sec_buf_len != 0) {
245 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 64);
246 if (skip < 0) {
247 err = EBADRPC;
248 goto errout;
249 }
250 if (skip > 0) {
251 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
252 }
253
254 /*
255 * Copy the security blob out to user space.
256 * Buffer addr,size in vc_auth_rbuf,rlen
257 */
258 if (wk->wk_u_auth_rlen < sec_buf_len) {
259 SMBSDEBUG("vc_auth_rbuf too small");
260 /* Give caller required size. */
261 wk->wk_u_auth_rlen = sec_buf_len;
262 err = EMSGSIZE;
263 goto errout;
264 }
265 wk->wk_u_auth_rlen = sec_buf_len;
266 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr,
267 sec_buf_len, MB_MUSER);
268 if (err) {
269 goto errout;
270 }
271 }
272
273 /*
274 * Decoded everything. Now decisions.
275 */
276
277 /*
278 * Turn on signing if either Server or client requires it,
279 * except: anonymous sessions can't sign.
280 */
281 if ((sp->sv2_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
282 (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED))
283 will_sign = B_TRUE;
284 if (vcp->vc_vopt & SMBVOPT_ANONYMOUS)
285 will_sign = B_FALSE;
286 SMBSDEBUG("Security signatures: %d", (int)will_sign);
287 if (will_sign)
288 vcp->vc_flags |= SMBV_SIGNING;
289
290 /*
291 * ToDo - too many places are looking at sv_caps, so for now
292 * set the SMB1 capabilities too. Later we should use the
293 * sv2_capabilities for SMB 2+.
294 */
295 sp->sv_caps = (SMB_CAP_UNICODE |
296 SMB_CAP_LARGE_FILES |
297 SMB_CAP_STATUS32 |
298 SMB_CAP_LARGE_READX |
299 SMB_CAP_LARGE_WRITEX |
300 SMB_CAP_EXT_SECURITY);
301 if (sp->sv2_capabilities & SMB2_CAP_DFS)
302 sp->sv_caps |= SMB_CAP_DFS;
303
304 /*
305 * A few sanity checks on what we received,
306 * becuse we will send these in ssnsetup.
307 *
308 * Maximum outstanding requests (we care),
309 * and Max. VCs (we only use one). Also,
310 * MaxBufferSize lower limit per spec.
311 */
312 if (sp->sv2_maxread < 0x8000) {
313 SMBSDEBUG("maxread too small\n");
314 err = ENOTSUP;
315 goto errout;
316 }
317 if (sp->sv2_maxwrite < 0x8000) {
318 SMBSDEBUG("maxwrite too small\n");
319 err = ENOTSUP;
320 goto errout;
321 }
322 if (sp->sv2_maxtransact < 0x4000) {
323 SMBSDEBUG("maxtransact too small\n");
324 err = ENOTSUP;
325 goto errout;
326 }
327
328 /* Here too, fill SMB1 fields */
329 vcp->vc_rxmax = sp->sv2_maxread;
330 vcp->vc_wxmax = sp->sv2_maxwrite;
331 vcp->vc_txmax = sp->sv2_maxtransact;
332
333 smb_rq_done(rqp);
334 return (0);
335
336 errout:
337 smb_rq_done(rqp);
338 if (err == 0)
339 err = EBADRPC;
340 return (err);
341 }
342
343 int
smb2_smb_ssnsetup(struct smb_vc * vcp,struct smb_cred * scred)344 smb2_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
345 {
346 // smb_sopt_t *sv = &vcp->vc_sopt;
347 smbioc_ssn_work_t *wk = &vcp->vc_work;
348 struct smb_rq *rqp = NULL;
349 struct mbchain *mbp = NULL;
350 struct mdchain *mdp = NULL;
351 char *sb;
352 int err, ret;
353 uint16_t sblen;
354 uint16_t length = 0;
355 uint16_t session_flags;
356 uint16_t sec_buf_off;
357 uint16_t sec_buf_len;
358 uint8_t security_mode;
359
360 /*
361 * Compute security mode
362 */
363 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
364 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
365 } else {
366 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
367 }
368
369 sb = wk->wk_u_auth_wbuf.lp_ptr;
370 sblen = (uint16_t)wk->wk_u_auth_wlen;
371
372 err = smb_rq_alloc(VCTOCP(vcp), SMB2_SESSION_SETUP, scred, &rqp);
373 if (err != 0) {
374 ret = err;
375 goto out;
376 }
377
378 /*
379 * Always ask for some credits. The server usually will
380 * only grant these credits once we've authenticated.
381 */
382 rqp->sr2_creditsrequested = smb2_ss_req_credits;
383
384 /*
385 * Build the SMB Session Setup request.
386 */
387 smb_rq_getrequest(rqp, &mbp);
388
389 mb_put_uint16le(mbp, 25); /* Struct size */
390 mb_put_uint8(mbp, 0); /* VcNumber */
391 mb_put_uint8(mbp, security_mode);
392 mb_put_uint32le(mbp, smb2_clnt_caps); /* Capabilities */
393 mb_put_uint32le(mbp, 0); /* Channel - always 0 */
394
395 /*
396 * Security buffer offset and length. Normally would use
397 * ptr = mb_reserve() and fill in later, but since only a
398 * small amount of fixed-size stuff follows (12 bytes)
399 * we can just compute the offset now.
400 */
401 mb_put_uint16le(mbp, mbp->mb_count + 12);
402 mb_put_uint16le(mbp, sblen);
403 mb_put_uint64le(mbp, vcp->vc2_prev_session_id);
404 err = mb_put_mem(mbp, sb, sblen, MB_MUSER);
405 if (err != 0) {
406 ret = err;
407 goto out;
408 }
409
410 /*
411 * Run the request. The return value here should be the
412 * return from this function, unless we fail decoding.
413 * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and
414 * the caller expects EINPROGRESS for that case.
415 */
416 ret = smb2_rq_internal(rqp, smb2_timo_logon);
417 if (ret != 0)
418 goto out;
419 switch (rqp->sr_error) {
420 case NT_STATUS_SUCCESS:
421 break;
422 case NT_STATUS_MORE_PROCESSING_REQUIRED:
423 /* Keep going, but return... */
424 ret = EINPROGRESS;
425 break;
426 default:
427 ret = EAUTH;
428 goto out;
429 }
430
431 /*
432 * After the first Session Setup Response,
433 * save the session ID.
434 */
435 if (vcp->vc2_session_id == 0)
436 vcp->vc2_session_id = rqp->sr2_rspsessionid;
437
438 /*
439 * Decode the session setup response
440 */
441 smb_rq_getreply(rqp, &mdp);
442
443 md_get_uint16le(mdp, &length); /* Struct size */
444 if (length != 9) {
445 ret = EBADRPC;
446 goto out;
447 }
448
449 md_get_uint16le(mdp, &session_flags);
450 md_get_uint16le(mdp, &sec_buf_off);
451 err = md_get_uint16le(mdp, &sec_buf_len);
452 if (err != 0) {
453 ret = err;
454 goto out;
455 }
456
457 /*
458 * Security buffer offset is from the beginning of SMB 2 Header
459 * Calculate how much further we have to go to get to it.
460 * Current offset is: SMB2_HDRLEN + 8
461 */
462 if (sec_buf_len != 0) {
463 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 8);
464 if (skip < 0) {
465 ret = EBADRPC;
466 goto out;
467 }
468 if (skip > 0) {
469 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
470 }
471
472 /*
473 * Copy the security blob out to user space.
474 * Buffer addr,size in vc_auth_rbuf,rlen
475 */
476 if (wk->wk_u_auth_rlen < sec_buf_len) {
477 SMBSDEBUG("vc_auth_rbuf too small");
478 /* Give caller required size. */
479 wk->wk_u_auth_rlen = sec_buf_len;
480 ret = EMSGSIZE;
481 goto out;
482 }
483 wk->wk_u_auth_rlen = sec_buf_len;
484 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr,
485 sec_buf_len, MB_MUSER);
486 if (err != 0) {
487 ret = err;
488 goto out;
489 }
490 }
491
492 out:
493 if (err != 0 && err != EINPROGRESS) {
494 /* Session ID no longer valid. */
495 vcp->vc2_session_id = 0;
496 }
497 if (rqp)
498 smb_rq_done(rqp);
499
500 return (ret);
501 }
502
503 int
smb2_smb_logoff(struct smb_vc * vcp,struct smb_cred * scred)504 smb2_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred)
505 {
506 struct smb_rq *rqp;
507 struct mbchain *mbp;
508 int error;
509
510 if (vcp->vc2_session_id == 0)
511 return (0);
512
513 error = smb_rq_alloc(VCTOCP(vcp), SMB2_LOGOFF, scred, &rqp);
514 if (error)
515 return (error);
516
517 /*
518 * Fill in Logoff part
519 */
520 smb_rq_getrequest(rqp, &mbp);
521 mb_put_uint16le(mbp, 4); /* Struct size */
522 mb_put_uint16le(mbp, 0); /* Reserved */
523
524 /*
525 * Run this with a relatively short timeout. (5 sec.)
526 * We don't really care about the result here.
527 * Also, don't reconnect for this, of course!
528 */
529 rqp->sr_flags |= SMBR_NORECONNECT;
530 error = smb2_rq_internal(rqp, 5);
531 smb_rq_done(rqp);
532 return (error);
533 }
534
535 int
smb2_smb_treeconnect(struct smb_share * ssp,struct smb_cred * scred)536 smb2_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
537 {
538 struct smb_vc *vcp;
539 struct smb_rq *rqp = NULL;
540 struct mbchain *mbp;
541 struct mdchain *mdp;
542 char *unc_name = NULL;
543 int error, unc_len;
544 uint16_t plen, *plenp;
545 uint16_t options = 0;
546 uint_t cnt0;
547 uint32_t net_stype;
548 uint16_t structure_size = 0;
549 uint8_t smb2stype;
550
551 vcp = SSTOVC(ssp);
552
553 /*
554 * Make this a "VC-level" request, so it will have
555 * rqp->sr_share == NULL, and smb_iod_sendrq()
556 * will send it with TID = SMB_TID_UNKNOWN
557 *
558 * This also serves to bypass the wait for
559 * share state changes, which this call is
560 * trying to carry out.
561 */
562 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_CONNECT, scred, &rqp);
563 if (error)
564 return (error);
565
566 /*
567 * Build the UNC name, i.e. "//server/share"
568 * but with backslashes of course.
569 * size math: three slashes, one null.
570 */
571 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name);
572 unc_name = kmem_alloc(unc_len, KM_SLEEP);
573 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s",
574 vcp->vc_srvname, ssp->ss_name);
575 SMBSDEBUG("unc_name: \"%s\"", unc_name);
576
577 /*
578 * Build the request.
579 */
580 mbp = &rqp->sr_rq;
581
582 mb_put_uint16le(mbp, 9); /* Struct size */
583 mb_put_uint16le(mbp, 0); /* Reserved */
584 mb_put_uint16le(mbp, 72); /* Path Offset */
585
586 /*
587 * Fill in path length after we put the string, so we know
588 * the length after conversion from UTF-8 to UCS-2.
589 */
590 plenp = mb_reserve(mbp, 2);
591 cnt0 = mbp->mb_count;
592
593 /* UNC resource name (without the null) */
594 error = smb_put_dmem(mbp, vcp, unc_name, unc_len - 1,
595 SMB_CS_NONE, NULL);
596 if (error)
597 goto out;
598
599 /* Now go back and fill in the path length. */
600 plen = (uint16_t)(mbp->mb_count - cnt0);
601 *plenp = htoles(plen);
602
603 /*
604 * Run the request.
605 *
606 * Using NOINTR_RECV because we don't want to risk
607 * missing a successful tree connect response,
608 * which would "leak" Tree IDs.
609 */
610 rqp->sr_flags |= SMBR_NOINTR_RECV;
611 error = smb2_rq_simple(rqp);
612 SMBSDEBUG("%d\n", error);
613 if (error) {
614 /*
615 * If we get the server name wrong, i.e. due to
616 * mis-configured name services, this will be
617 * NT_STATUS_DUPLICATE_NAME. Log this error.
618 */
619 SMBERROR("(%s) failed, status=0x%x",
620 unc_name, rqp->sr_error);
621 goto out;
622 }
623
624 /*
625 * Parse the tree connect response
626 */
627 smb_rq_getreply(rqp, &mdp);
628
629 /* Check structure size is 16 */
630 md_get_uint16le(mdp, &structure_size);
631 if (structure_size != 16) {
632 error = EBADRPC;
633 goto out;
634 }
635
636 md_get_uint8(mdp, &smb2stype);
637 md_get_uint8(mdp, NULL); /* reserved */
638 md_get_uint32le(mdp, &ssp->ss2_share_flags);
639 md_get_uint32le(mdp, &ssp->ss2_share_caps);
640 error = md_get_uint32le(mdp, NULL); /* maxAccessRights */
641 if (error)
642 goto out;
643
644 /*
645 * Convert SMB2 share type to NetShareEnum share type
646 */
647 switch (smb2stype) {
648 case SMB2_SHARE_TYPE_DISK:
649 net_stype = STYPE_DISKTREE;
650 break;
651 case SMB2_SHARE_TYPE_PIPE:
652 net_stype = STYPE_IPC;
653 break;
654 case SMB2_SHARE_TYPE_PRINT:
655 net_stype = STYPE_PRINTQ;
656 break;
657 default:
658 net_stype = STYPE_UNKNOWN;
659 break;
660 }
661 ssp->ss_type = net_stype;
662
663 /*
664 * Map SMB 2/3 capabilities to SMB 1 options,
665 * for common code that looks there.
666 */
667 if (ssp->ss2_share_caps & SMB2_SHARE_CAP_DFS)
668 options |= SMB_SHARE_IS_IN_DFS;
669
670 /* Update share state */
671 SMB_SS_LOCK(ssp);
672 ssp->ss2_tree_id = rqp->sr2_rsptreeid;
673 ssp->ss_vcgenid = vcp->vc_genid;
674 ssp->ss_options = options;
675 ssp->ss_flags |= SMBS_CONNECTED;
676 SMB_SS_UNLOCK(ssp);
677
678 out:
679 if (unc_name)
680 kmem_free(unc_name, unc_len);
681 smb_rq_done(rqp);
682 return (error);
683 }
684
685 int
smb2_smb_treedisconnect(struct smb_share * ssp,struct smb_cred * scred)686 smb2_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
687 {
688 struct smb_vc *vcp;
689 struct smb_rq *rqp;
690 struct mbchain *mbp;
691 int error;
692
693 if (ssp->ss2_tree_id == SMB2_TID_UNKNOWN)
694 return (0);
695
696 /*
697 * Build this as a "VC-level" request, so it will
698 * avoid testing the _GONE flag on the share,
699 * which has already been set at this point.
700 * Add the share pointer "by hand" below, so
701 * smb_iod_sendrq will plug in the TID.
702 */
703 vcp = SSTOVC(ssp);
704 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_DISCONNECT, scred, &rqp);
705 if (error)
706 return (error);
707 rqp->sr_share = ssp; /* See "by hand" above. */
708
709 /*
710 * Fill in SMB2 Tree Disconnect part
711 */
712 smb_rq_getrequest(rqp, &mbp);
713 mb_put_uint16le(mbp, 4); /* Struct size */
714 mb_put_uint16le(mbp, 0); /* Reserved */
715
716 /*
717 * Run this with a relatively short timeout. (5 sec.)
718 * We don't really care about the result here, but we
719 * do need to make sure we send this out, or we could
720 * "leak" active tree IDs on interrupt or timeout.
721 * The NOINTR_SEND flag makes this request immune to
722 * interrupt or timeout until the send is done.
723 * Also, don't reconnect for this, of course!
724 */
725 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
726 error = smb2_rq_simple_timed(rqp, 5);
727
728 smb_rq_done(rqp);
729
730 /* Whether we get an error or not... */
731 ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
732
733 return (error);
734 }
735
736 /*
737 * Put the name, first skipping a leading slash.
738 */
739 static int
put_name_skip_slash(struct mbchain * mbp,struct mbchain * name_mbp)740 put_name_skip_slash(struct mbchain *mbp, struct mbchain *name_mbp)
741 {
742 mblk_t *m;
743
744 if (name_mbp == NULL)
745 return (0);
746 m = name_mbp->mb_top;
747 if (m == NULL)
748 return (0);
749
750 /* Use a dup of the message to leave the passed one untouched. */
751 m = dupmsg(m);
752 if (m == NULL)
753 return (ENOSR);
754
755 if (MBLKL(m) >= 2 &&
756 m->b_rptr[0] == '\\' &&
757 m->b_rptr[1] == '\0')
758 m->b_rptr += 2;
759
760 return (mb_put_mbuf(mbp, m));
761 }
762
763 /*
764 * Modern create/open of file or directory.
765 *
766 * The passed name is a full path relative to the share root.
767 * Callers prepare paths with a leading slash (backslash)
768 * because that's what SMB1 expected. SMB2 does not allow the
769 * leading slash here. To make life simpler for callers skip a
770 * leading slash here. That allows callers use use common logic
771 * for building paths without needing to know if the connection
772 * is using SMB1 or SMB2 (just build paths with a leading slash).
773 */
774 int
smb2_smb_ntcreate(struct smb_share * ssp,struct mbchain * name_mb,struct mbchain * cctx_in,struct mdchain * cctx_out,uint32_t cr_flags,uint32_t req_acc,uint32_t efa,uint32_t share_acc,uint32_t open_disp,uint32_t createopt,uint32_t impersonate,struct smb_cred * scrp,smb2fid_t * fidp,uint32_t * cr_act_p,struct smbfattr * fap)775 smb2_smb_ntcreate(
776 struct smb_share *ssp,
777 struct mbchain *name_mb,
778 struct mbchain *cctx_in,
779 struct mdchain *cctx_out,
780 uint32_t cr_flags, /* create flags */
781 uint32_t req_acc, /* requested access */
782 uint32_t efa, /* ext. file attrs (DOS attr +) */
783 uint32_t share_acc,
784 uint32_t open_disp, /* open disposition */
785 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
786 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */
787 struct smb_cred *scrp,
788 smb2fid_t *fidp, /* returned FID */
789 uint32_t *cr_act_p, /* optional create action */
790 struct smbfattr *fap) /* optional attributes */
791 {
792 struct smbfattr fa;
793 struct smb_rq *rqp;
794 struct mbchain *mbp;
795 struct mdchain *mdp;
796 uint16_t *name_offp;
797 uint16_t *name_lenp;
798 uint32_t *cctx_offp;
799 uint32_t *cctx_lenp;
800 uint32_t rcc_off, rcc_len;
801 smb2fid_t smb2_fid;
802 uint64_t llongint;
803 uint32_t longint, createact;
804 uint_t off, len;
805 int error;
806 uint16_t StructSize = 57; // [MS-SMB2]
807
808 bzero(&fa, sizeof (fa));
809
810 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CREATE, scrp, &rqp);
811 if (error)
812 return (error);
813
814 /*
815 * Todo: Assemble creat contexts (if needed)
816 * into an mbchain.
817 */
818
819 /*
820 * Build the SMB 2/3 Create Request
821 */
822 smb_rq_getrequest(rqp, &mbp);
823 mb_put_uint16le(mbp, StructSize);
824 mb_put_uint8(mbp, 0); /* Security flags */
825 mb_put_uint8(mbp, SMB2_OPLOCK_LEVEL_NONE); /* Oplock level */
826 mb_put_uint32le(mbp, impersonate); /* Impersonation Level */
827 mb_put_uint64le(mbp, cr_flags);
828 mb_put_uint64le(mbp, 0); /* Reserved */
829 mb_put_uint32le(mbp, req_acc);
830 mb_put_uint32le(mbp, efa); /* File attributes */
831 mb_put_uint32le(mbp, share_acc); /* Share access */
832 mb_put_uint32le(mbp, open_disp); /* Create disposition */
833 mb_put_uint32le(mbp, createopt); /* Create options */
834
835 name_offp = mb_reserve(mbp, 2); /* Name offset */
836 name_lenp = mb_reserve(mbp, 2); /* Name len */
837
838 cctx_offp = mb_reserve(mbp, 4); /* Context offset */
839 cctx_lenp = mb_reserve(mbp, 4); /* Context len */
840
841 /*
842 * Put the file name, which is provided in an mbchain.
843 * If there's a leading slash, skip it (see above).
844 */
845 off = mbp->mb_count;
846 *name_offp = htoles((uint16_t)off);
847 error = put_name_skip_slash(mbp, name_mb);
848 if (error)
849 goto out;
850 len = mbp->mb_count - off;
851 *name_lenp = htoles((uint16_t)len);
852
853 /*
854 * Now the create contexts (if provided)
855 */
856 if (cctx_in != NULL) {
857 off = mbp->mb_count;
858 *cctx_offp = htolel((uint32_t)off);
859 mb_put_mbchain(mbp, cctx_in);
860 len = mbp->mb_count - off;
861 *cctx_lenp = htolel((uint32_t)len);
862 } else {
863 *cctx_offp = 0;
864 *cctx_lenp = 0;
865 }
866
867 /*
868 * If we didn't put any variable-sized data, we'll have
869 * put exactly 56 bytes of data, and we need to pad out
870 * this request to the 57 bytes StructSize indicated.
871 */
872 if (mbp->mb_count < (StructSize + SMB2_HDRLEN))
873 mb_put_uint8(mbp, 0);
874
875 /*
876 * Don't want to risk missing a successful
877 * open response, or we could "leak" FIDs.
878 */
879 rqp->sr_flags |= SMBR_NOINTR_RECV;
880 error = smb2_rq_simple_timed(rqp, smb2_timo_open);
881 if (error)
882 goto out;
883
884 /*
885 * Parse SMB 2/3 Create Response
886 */
887 smb_rq_getreply(rqp, &mdp);
888
889 /* Check structure size is 89 */
890 error = md_get_uint16le(mdp, &StructSize);
891 if (StructSize != 89) {
892 error = EBADRPC;
893 goto out;
894 }
895
896 md_get_uint8(mdp, NULL); /* oplock lvl granted */
897 md_get_uint8(mdp, NULL); /* mbz */
898 md_get_uint32le(mdp, &createact); /* create_action */
899 md_get_uint64le(mdp, &llongint); /* creation time */
900 smb_time_NT2local(llongint, &fa.fa_createtime);
901 md_get_uint64le(mdp, &llongint); /* access time */
902 smb_time_NT2local(llongint, &fa.fa_atime);
903 md_get_uint64le(mdp, &llongint); /* write time */
904 smb_time_NT2local(llongint, &fa.fa_mtime);
905 md_get_uint64le(mdp, &llongint); /* change time */
906 smb_time_NT2local(llongint, &fa.fa_ctime);
907 md_get_uint64le(mdp, &llongint); /* allocation size */
908 fa.fa_allocsz = llongint;
909 md_get_uint64le(mdp, &llongint); /* EOF position */
910 fa.fa_size = llongint;
911 md_get_uint32le(mdp, &longint); /* attributes */
912 fa.fa_attr = longint;
913 md_get_uint32le(mdp, NULL); /* reserved */
914
915 /* Get SMB 2/3 File ID and create user fid to return */
916 md_get_uint64le(mdp, &smb2_fid.fid_persistent);
917 error = md_get_uint64le(mdp, &smb2_fid.fid_volatile);
918 if (error)
919 goto out;
920
921 /* Get Context Offset */
922 error = md_get_uint32le(mdp, &rcc_off);
923 if (error)
924 goto out;
925 /* Get Context Length */
926 error = md_get_uint32le(mdp, &rcc_len);
927 if (error)
928 goto out;
929
930 /*
931 * If the caller wants the returned create contexts, parse.
932 * Context offset is from the beginning of SMB 2/3 Header
933 * Calculate how much further we have to go to get to it.
934 * Current offset is: SMB2_HDRLEN + 88
935 */
936 if (rcc_len != 0) {
937 int skip = (int)rcc_off - (SMB2_HDRLEN + 88);
938 if (skip < 0) {
939 error = EBADRPC;
940 goto out;
941 }
942 if (skip > 0) {
943 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
944 }
945 if (cctx_out != NULL) {
946 mblk_t *m = NULL;
947 error = md_get_mbuf(mdp, rcc_len, &m);
948 if (error)
949 goto out;
950 md_initm(cctx_out, m);
951 }
952 }
953
954 out:
955 smb_rq_done(rqp);
956 if (error)
957 return (error);
958
959 *fidp = smb2_fid;
960 if (cr_act_p)
961 *cr_act_p = createact;
962 if (fap)
963 *fap = fa; /* struct copy */
964
965 return (0);
966 }
967
968 int
smb2_smb_close(struct smb_share * ssp,smb2fid_t * fid,struct smb_cred * scrp)969 smb2_smb_close(struct smb_share *ssp, smb2fid_t *fid, struct smb_cred *scrp)
970 {
971 struct smb_rq *rqp;
972 struct mbchain *mbp;
973 int error;
974
975 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CLOSE, scrp, &rqp);
976 if (error)
977 return (error);
978
979 /*
980 * Build the SMB 2/3 Close Request
981 */
982 smb_rq_getrequest(rqp, &mbp);
983 mb_put_uint16le(mbp, 24); /* Struct size */
984 mb_put_uint16le(mbp, 0); /* Flags */
985 mb_put_uint32le(mbp, 0); /* Reserved */
986
987 mb_put_uint64le(mbp, fid->fid_persistent);
988 mb_put_uint64le(mbp, fid->fid_volatile);
989
990 /* Make sure we send, but only if already connected */
991 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
992 error = smb2_rq_simple(rqp);
993 smb_rq_done(rqp);
994 return (error);
995 }
996
997 int
smb2_smb_ioctl(struct smb_share * ssp,smb2fid_t * fid,struct mbchain * data_in,struct mdchain * data_out,uint32_t * data_out_sz,uint32_t ctl_code,struct smb_cred * scrp)998 smb2_smb_ioctl(
999 struct smb_share *ssp,
1000 smb2fid_t *fid,
1001 struct mbchain *data_in,
1002 struct mdchain *data_out,
1003 uint32_t *data_out_sz, /* max / returned */
1004 uint32_t ctl_code,
1005 struct smb_cred *scrp)
1006 {
1007 struct smb_rq *rqp;
1008 struct mbchain *mbp;
1009 struct mdchain *mdp;
1010 uint32_t *data_in_offp;
1011 uint32_t *data_in_lenp;
1012 uint32_t data_out_off;
1013 uint32_t data_out_len;
1014 uint16_t length = 0;
1015 uint_t off, len;
1016 int error;
1017
1018 error = smb_rq_alloc(SSTOCP(ssp), SMB2_IOCTL, scrp, &rqp);
1019 if (error)
1020 return (error);
1021
1022 /*
1023 * Build the SMB 2 IOCTL Request
1024 */
1025 smb_rq_getrequest(rqp, &mbp);
1026 mb_put_uint16le(mbp, 57); /* Struct size */
1027 mb_put_uint16le(mbp, 0); /* Reserved */
1028 mb_put_uint32le(mbp, ctl_code);
1029
1030 mb_put_uint64le(mbp, fid->fid_persistent);
1031 mb_put_uint64le(mbp, fid->fid_volatile);
1032
1033 data_in_offp = mb_reserve(mbp, 4);
1034 data_in_lenp = mb_reserve(mbp, 4);
1035 mb_put_uint32le(mbp, 0); /* Max input resp */
1036
1037 mb_put_uint32le(mbp, 0); /* Output offset */
1038 mb_put_uint32le(mbp, 0); /* Output count */
1039 mb_put_uint32le(mbp, *data_out_sz);
1040
1041 mb_put_uint32le(mbp, SMB2_IOCTL_IS_FSCTL); /* Flags */
1042 mb_put_uint32le(mbp, 0); /* Reserved2 */
1043
1044 /*
1045 * Now data_in (if provided)
1046 */
1047 if (data_in != NULL) {
1048 off = mbp->mb_count;
1049 *data_in_offp = htolel((uint32_t)off);
1050 mb_put_mbchain(mbp, data_in);
1051 len = mbp->mb_count - off;
1052 *data_in_lenp = htolel((uint32_t)len);
1053 } else {
1054 *data_in_offp = 0;
1055 *data_in_lenp = 0;
1056 }
1057
1058 /*
1059 * Run the request
1060 */
1061 error = smb2_rq_simple_timed(rqp, smb2_timo_default);
1062 if (error)
1063 goto out;
1064
1065 /*
1066 * Parse SMB 2 Ioctl Response
1067 */
1068 smb_rq_getreply(rqp, &mdp);
1069
1070 /* Check structure size is 49 */
1071 md_get_uint16le(mdp, &length);
1072 if (length != 49) {
1073 error = EBADRPC;
1074 goto out;
1075 }
1076 md_get_uint16le(mdp, NULL); /* reserved */
1077 md_get_uint32le(mdp, NULL); /* Get CtlCode */
1078 md_get_uint64le(mdp, NULL); /* fid_persistent */
1079 md_get_uint64le(mdp, NULL); /* fid_volatile */
1080 md_get_uint32le(mdp, NULL); /* Get Input offset */
1081 md_get_uint32le(mdp, NULL); /* Get Input count */
1082
1083 error = md_get_uint32le(mdp, &data_out_off);
1084 if (error)
1085 goto out;
1086 error = md_get_uint32le(mdp, &data_out_len);
1087 if (error)
1088 goto out;
1089
1090 md_get_uint32le(mdp, NULL); /* Flags */
1091 md_get_uint32le(mdp, NULL); /* reserved */
1092
1093 /*
1094 * If the caller wants the ioctl output data, parse.
1095 * Current offset is: SMB2_HDRLEN + 48
1096 * Always return the received length.
1097 */
1098 *data_out_sz = data_out_len;
1099 if (data_out_len != 0) {
1100 int skip = (int)data_out_off - (SMB2_HDRLEN + 48);
1101 if (skip < 0) {
1102 error = EBADRPC;
1103 goto out;
1104 }
1105 if (skip > 0) {
1106 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
1107 }
1108 if (data_out != NULL) {
1109 mblk_t *m = NULL;
1110 error = md_get_mbuf(mdp, data_out_len, &m);
1111 if (error)
1112 goto out;
1113 md_initm(data_out, m);
1114 }
1115 }
1116
1117 out:
1118 smb_rq_done(rqp);
1119
1120 return (error);
1121 }
1122
1123 int
smb2_smb_read(smb_fh_t * fhp,uint32_t * lenp,uio_t * uiop,smb_cred_t * scred,int timo)1124 smb2_smb_read(smb_fh_t *fhp, uint32_t *lenp,
1125 uio_t *uiop, smb_cred_t *scred, int timo)
1126 {
1127 struct smb_share *ssp = FHTOSS(fhp);
1128 struct smb_rq *rqp;
1129 struct mbchain *mbp;
1130 struct mdchain *mdp;
1131 int error;
1132 uint64_t off64 = uiop->uio_loffset;
1133 uint32_t rlen;
1134 uint16_t length = 0;
1135 uint8_t data_offset;
1136
1137 error = smb_rq_alloc(SSTOCP(ssp), SMB2_READ, scred, &rqp);
1138 if (error)
1139 return (error);
1140
1141 /*
1142 * Build the SMB 2 Read Request
1143 */
1144 smb_rq_getrequest(rqp, &mbp);
1145 mb_put_uint16le(mbp, 49); /* Struct size */
1146 mb_put_uint16le(mbp, 0); /* Padding and Reserved */
1147
1148 mb_put_uint32le(mbp, *lenp); /* Length of read */
1149 mb_put_uint64le(mbp, off64); /* Offset */
1150
1151 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent);
1152 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile);
1153
1154 mb_put_uint32le(mbp, 1); /* MinCount */
1155 /* (only indicates blocking) */
1156
1157 mb_put_uint32le(mbp, 0); /* Channel */
1158 mb_put_uint32le(mbp, 0); /* Remaining */
1159 mb_put_uint32le(mbp, 0); /* Channel offset/len */
1160 mb_put_uint8(mbp, 0); /* data "blob" (pad) */
1161
1162 if (timo == 0)
1163 timo = smb2_timo_read;
1164 error = smb2_rq_simple_timed(rqp, timo);
1165 if (error)
1166 goto out;
1167
1168 /*
1169 * Parse SMB 2 Read Response
1170 */
1171 smb_rq_getreply(rqp, &mdp);
1172
1173 /* Check structure size is 17 */
1174 md_get_uint16le(mdp, &length);
1175 if (length != 17) {
1176 error = EBADRPC;
1177 goto out;
1178 }
1179 md_get_uint8(mdp, &data_offset);
1180 md_get_uint8(mdp, NULL); /* reserved */
1181
1182 /* Get Data Length read */
1183 error = md_get_uint32le(mdp, &rlen);
1184 if (error)
1185 goto out;
1186
1187 md_get_uint32le(mdp, NULL); /* Data Remaining (always 0) */
1188 md_get_uint32le(mdp, NULL); /* Get Reserved2 (always 0) */
1189
1190 /*
1191 * Data offset is from the beginning of SMB 2/3 Header
1192 * Calculate how much further we have to go to get to it.
1193 */
1194 if (data_offset < (SMB2_HDRLEN + 16)) {
1195 error = EBADRPC;
1196 goto out;
1197 }
1198 if (data_offset > (SMB2_HDRLEN + 16)) {
1199 int skip = data_offset - (SMB2_HDRLEN + 16);
1200 md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
1201 }
1202
1203 /*
1204 * Get the data
1205 */
1206 if (rlen == 0) {
1207 *lenp = rlen;
1208 goto out;
1209 }
1210 /* paranoid */
1211 if (rlen > *lenp) {
1212 SMBSDEBUG("bad server! rlen %d, len %d\n",
1213 rlen, *lenp);
1214 rlen = *lenp;
1215 }
1216
1217 error = md_get_uio(mdp, uiop, rlen);
1218 if (error)
1219 goto out;
1220
1221 /* Success */
1222 *lenp = rlen;
1223
1224 out:
1225 smb_rq_done(rqp);
1226 return (error);
1227 }
1228
1229 int
smb2_smb_write(smb_fh_t * fhp,uint32_t * lenp,uio_t * uiop,smb_cred_t * scred,int timo)1230 smb2_smb_write(smb_fh_t *fhp, uint32_t *lenp,
1231 uio_t *uiop, smb_cred_t *scred, int timo)
1232 {
1233 struct smb_share *ssp = FHTOSS(fhp);
1234 struct smb_rq *rqp;
1235 struct mbchain *mbp;
1236 struct mdchain *mdp;
1237 int error;
1238 uint64_t off64 = uiop->uio_loffset;
1239 uint32_t rlen;
1240 uint16_t data_offset;
1241 uint16_t length = 0;
1242
1243 error = smb_rq_alloc(SSTOCP(ssp), SMB2_WRITE, scred, &rqp);
1244 if (error)
1245 return (error);
1246
1247 /*
1248 * Build the SMB 2 Write Request
1249 */
1250 smb_rq_getrequest(rqp, &mbp);
1251 mb_put_uint16le(mbp, 49); /* Struct size */
1252 data_offset = SMB2_HDRLEN + 48;
1253 mb_put_uint16le(mbp, data_offset); /* Data Offset */
1254 mb_put_uint32le(mbp, *lenp); /* Length of write */
1255 mb_put_uint64le(mbp, off64); /* Offset */
1256
1257 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent);
1258 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile);
1259
1260 mb_put_uint32le(mbp, 0); /* Channel */
1261 mb_put_uint32le(mbp, 0); /* Remaining */
1262 mb_put_uint32le(mbp, 0); /* Channel offset/len */
1263 mb_put_uint32le(mbp, 0); /* Write flags */
1264
1265 error = mb_put_uio(mbp, uiop, *lenp);
1266 if (error)
1267 goto out;
1268
1269 if (timo == 0)
1270 timo = smb2_timo_write;
1271 error = smb2_rq_simple_timed(rqp, timo);
1272 if (error)
1273 goto out;
1274
1275 /*
1276 * Parse SMB 2/3 Write Response
1277 */
1278 smb_rq_getreply(rqp, &mdp);
1279
1280 /* Check structure size is 17 */
1281 md_get_uint16le(mdp, &length);
1282 if (length != 17) {
1283 error = EBADRPC;
1284 goto out;
1285 }
1286
1287 md_get_uint16le(mdp, NULL); /* Get Reserved */
1288
1289 /* Get Data Length written */
1290 error = md_get_uint32le(mdp, &rlen);
1291 if (error)
1292 goto out;
1293
1294 /* Get Data Remaining (always 0) */
1295 md_get_uint32le(mdp, NULL);
1296
1297 /* Get Reserved2 (always 0) */
1298 md_get_uint32le(mdp, NULL);
1299
1300 /* Success */
1301 *lenp = rlen;
1302
1303 out:
1304 smb_rq_done(rqp);
1305 return (error);
1306 }
1307
1308 /*
1309 * Note: the IOD calls this, so this request must not wait for
1310 * connection state changes, etc. (uses smb2_rq_internal)
1311 */
1312 int
smb2_smb_echo(struct smb_vc * vcp,struct smb_cred * scred,int timo)1313 smb2_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1314 {
1315 struct smb_rq *rqp;
1316 struct mbchain *mbp;
1317 int error;
1318
1319 error = smb_rq_alloc(VCTOCP(vcp), SMB2_ECHO, scred, &rqp);
1320 if (error)
1321 return (error);
1322
1323 /*
1324 * Build the SMB 2 Echo Request
1325 */
1326 smb_rq_getrequest(rqp, &mbp);
1327 mb_put_uint16le(mbp, 4); /* Struct size */
1328 mb_put_uint16le(mbp, 0); /* Reserved */
1329
1330 rqp->sr_flags |= SMBR_NORECONNECT;
1331 error = smb2_rq_internal(rqp, timo);
1332
1333 smb_rq_done(rqp);
1334 return (error);
1335 }
1336