Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-15577 SMB2 ioct dfs_get_referral returns wrong error
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15577 SMB2 ioct dfs_get_referral returns wrong error
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_dfs.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_dfs.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 #include <smbsrv/smb_kproto.h>
29 29 #include <smbsrv/smb_dfs.h>
30 30 #include <smbsrv/smb_door.h>
31 -#include <smbsrv/winioctl.h>
31 +#include <smb/winioctl.h>
32 32
33 33 /*
34 34 * Get Referral response header flags
35 35 * For exact meaning refer to MS-DFSC spec.
36 36 *
37 37 * R: ReferralServers
38 38 * S: StorageServers
39 39 * T: TargetFailback
40 40 */
41 41 #define DFS_HDRFLG_R 0x00000001
42 42 #define DFS_HDRFLG_S 0x00000002
43 43 #define DFS_HDRFLG_T 0x00000004
44 44
45 45 /*
46 46 * Entry flags
47 47 */
48 48 #define DFS_ENTFLG_T 0x0004
49 49
50 50 /*
51 51 * Referral entry types/versions
52 52 */
53 53 #define DFS_REFERRAL_V1 0x0001
54 54 #define DFS_REFERRAL_V2 0x0002
55 55 #define DFS_REFERRAL_V3 0x0003
56 56 #define DFS_REFERRAL_V4 0x0004
57 57
58 58 /*
59 59 * Valid values for ServerType field in referral entries
60 60 */
61 61 #define DFS_SRVTYPE_NONROOT 0x0000
62 62 #define DFS_SRVTYPE_ROOT 0x0001
63 63
64 64 /*
65 65 * Size of the fix part for each referral entry type
66 66 */
67 67 #define DFS_REFV1_ENTSZ 8
68 68 #define DFS_REFV2_ENTSZ 22
69 69 #define DFS_REFV3_ENTSZ 34
70 70 #define DFS_REFV4_ENTSZ 34
71 71
72 72 static dfs_reftype_t smb_dfs_get_reftype(const char *);
73 73 static void smb_dfs_encode_hdr(mbuf_chain_t *, dfs_info_t *);
74 74 static uint32_t smb_dfs_encode_refv1(smb_request_t *, mbuf_chain_t *,
75 75 dfs_info_t *);
76 76 static uint32_t smb_dfs_encode_refv2(smb_request_t *, mbuf_chain_t *,
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
77 77 dfs_info_t *);
78 78 static uint32_t smb_dfs_encode_refv3x(smb_request_t *, mbuf_chain_t *,
79 79 dfs_info_t *, uint16_t);
80 80 static void smb_dfs_encode_targets(mbuf_chain_t *, dfs_info_t *);
81 81 static uint32_t smb_dfs_referrals_get(smb_request_t *, char *, dfs_reftype_t,
82 82 dfs_referral_response_t *);
83 83 static void smb_dfs_referrals_free(dfs_referral_response_t *);
84 84 static uint16_t smb_dfs_referrals_unclen(dfs_info_t *, uint16_t);
85 85
86 86 /*
87 + * Handle device type FILE_DEVICE_DFS
88 + * for smb2_ioctl
89 + */
90 +uint32_t
91 +smb_dfs_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
92 +{
93 + uint32_t status;
94 +
95 + if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
96 + return (NT_STATUS_INVALID_DEVICE_REQUEST);
97 +
98 + switch (fsctl->CtlCode) {
99 + case FSCTL_DFS_GET_REFERRALS:
100 + status = smb_dfs_get_referrals(sr, fsctl);
101 + break;
102 + case FSCTL_DFS_GET_REFERRALS_EX: /* XXX - todo */
103 + default:
104 + status = NT_STATUS_NOT_SUPPORTED;
105 + }
106 +
107 + return (status);
108 +}
109 +
110 +/*
87 111 * Note: SMB1 callers in smb_trans2_dfs.c
88 112 * smb_com_trans2_report_dfs_inconsistency
89 113 * smb_com_trans2_get_dfs_referral
90 114 */
91 115
92 116 /*
93 117 * See [MS-DFSC] for details about this command
118 + * Handles FSCTL_DFS_GET_REFERRALS (only)
94 119 */
95 120 uint32_t
96 121 smb_dfs_get_referrals(smb_request_t *sr, smb_fsctl_t *fsctl)
97 122 {
98 123 dfs_info_t *referrals;
99 124 dfs_referral_response_t refrsp;
100 125 dfs_reftype_t reftype;
101 126 char *path;
102 127 uint16_t maxver;
103 128 uint32_t status;
104 129 int rc;
105 130
106 131 /*
107 132 * The caller checks this, because the error reporting method
108 133 * varies across SMB versions.
109 134 */
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
110 135 ASSERT(STYPE_ISIPC(sr->tid_tree->t_res_type));
111 136
112 137 /*
113 138 * XXX Instead of decoding the referral request and encoding
114 139 * the response here (in-kernel) we could pass the given
115 140 * request buffer in our door call, and let that return the
116 141 * response buffer ready to stuff into out_mbc. That would
117 142 * allow all this decoding/encoding to happen at user-level.
118 143 * (and most of this file would go away. :-)
119 144 */
120 - switch (fsctl->CtlCode) {
121 - case FSCTL_DFS_GET_REFERRALS:
122 - /*
123 - * Input data is (w) MaxReferralLevel, (U) path
124 - */
125 - rc = smb_mbc_decodef(fsctl->in_mbc, "%wu",
126 - sr, &maxver, &path);
127 - if (rc != 0)
128 - return (NT_STATUS_INVALID_PARAMETER);
129 - break;
130 145
131 - case FSCTL_DFS_GET_REFERRALS_EX: /* XXX - todo */
132 - default:
133 - return (NT_STATUS_NOT_SUPPORTED);
134 - }
146 + /*
147 + * Input data is (w) MaxReferralLevel, (U) path
148 + */
149 + rc = smb_mbc_decodef(fsctl->in_mbc, "%wu",
150 + sr, &maxver, &path);
151 + if (rc != 0)
152 + return (NT_STATUS_INVALID_PARAMETER);
135 153
136 154 reftype = smb_dfs_get_reftype((const char *)path);
137 155 switch (reftype) {
138 156 case DFS_REFERRAL_INVALID:
139 157 /* Need to check the error for this case */
140 158 return (NT_STATUS_INVALID_PARAMETER);
141 159
142 160 case DFS_REFERRAL_DOMAIN:
143 161 case DFS_REFERRAL_DC:
144 162 /* MS-DFSC: this error is returned by non-DC root */
145 163 return (NT_STATUS_INVALID_PARAMETER);
146 164
147 165 case DFS_REFERRAL_SYSVOL:
148 166 /* MS-DFSC: this error is returned by non-DC root */
149 167 return (NT_STATUS_NO_SUCH_DEVICE);
150 168
151 169 default:
152 170 break;
153 171 }
154 172
155 173 status = smb_dfs_referrals_get(sr, path, reftype, &refrsp);
156 174 if (status != NT_STATUS_SUCCESS)
157 175 return (status);
158 176
159 177 referrals = &refrsp.rp_referrals;
160 178 smb_dfs_encode_hdr(fsctl->out_mbc, referrals);
161 179
162 180 /*
163 181 * Server may respond with any referral version at or below
164 182 * the maximum specified in the request.
165 183 */
166 184 switch (maxver) {
167 185 case DFS_REFERRAL_V1:
168 186 status = smb_dfs_encode_refv1(sr, fsctl->out_mbc, referrals);
169 187 break;
170 188
171 189 case DFS_REFERRAL_V2:
172 190 status = smb_dfs_encode_refv2(sr, fsctl->out_mbc, referrals);
173 191 break;
174 192
175 193 case DFS_REFERRAL_V3:
176 194 status = smb_dfs_encode_refv3x(sr, fsctl->out_mbc, referrals,
177 195 DFS_REFERRAL_V3);
178 196 break;
179 197
180 198 case DFS_REFERRAL_V4:
181 199 default:
182 200 status = smb_dfs_encode_refv3x(sr, fsctl->out_mbc, referrals,
183 201 DFS_REFERRAL_V4);
184 202 break;
185 203 }
186 204
187 205 smb_dfs_referrals_free(&refrsp);
188 206
189 207 return (status);
190 208 }
191 209
192 210 /*
193 211 * [MS-DFSC]: REQ_GET_DFS_REFERRAL
194 212 *
195 213 * Determines the referral type based on the specified path:
196 214 *
197 215 * Domain referral:
198 216 * ""
199 217 *
200 218 * DC referral:
201 219 * \<domain>
202 220 *
203 221 * Sysvol referral:
204 222 * \<domain>\SYSVOL
205 223 * \<domain>\NETLOGON
206 224 *
207 225 * Root referral:
208 226 * \<domain>\<dfsname>
209 227 * \<server>\<dfsname>
210 228 *
211 229 * Link referral:
212 230 * \<domain>\<dfsname>\<linkpath>
213 231 * \<server>\<dfsname>\<linkpath>
214 232 */
215 233 static dfs_reftype_t
216 234 smb_dfs_get_reftype(const char *path)
217 235 {
218 236 smb_unc_t unc;
219 237 dfs_reftype_t reftype = 0;
220 238
221 239 if (*path == '\0')
222 240 return (DFS_REFERRAL_DOMAIN);
223 241
224 242 if (smb_unc_init(path, &unc) != 0)
225 243 return (DFS_REFERRAL_INVALID);
226 244
227 245 if (unc.unc_path != NULL) {
228 246 reftype = DFS_REFERRAL_LINK;
229 247 } else if (unc.unc_share != NULL) {
230 248 if ((smb_strcasecmp(unc.unc_share, "SYSVOL", 0) == 0) ||
231 249 (smb_strcasecmp(unc.unc_share, "NETLOGON", 0) == 0)) {
232 250 reftype = DFS_REFERRAL_SYSVOL;
233 251 } else {
234 252 reftype = DFS_REFERRAL_ROOT;
235 253 }
236 254 } else if (unc.unc_server != NULL) {
237 255 reftype = DFS_REFERRAL_DC;
238 256 }
239 257
240 258 smb_unc_free(&unc);
241 259 return (reftype);
242 260 }
243 261
244 262 static void
245 263 smb_dfs_encode_hdr(mbuf_chain_t *mbc, dfs_info_t *referrals)
246 264 {
247 265 uint16_t path_consumed;
248 266 uint32_t flags;
249 267
250 268 path_consumed = smb_wcequiv_strlen(referrals->i_uncpath);
251 269 flags = DFS_HDRFLG_S;
252 270 if (referrals->i_type == DFS_OBJECT_ROOT)
253 271 flags |= DFS_HDRFLG_R;
254 272
255 273 /* Fill rep_param_mb in SMB1 caller. */
256 274 (void) smb_mbc_encodef(mbc, "wwl", path_consumed,
257 275 referrals->i_ntargets, flags);
258 276 }
259 277
260 278 static uint32_t
261 279 smb_dfs_encode_refv1(smb_request_t *sr, mbuf_chain_t *mbc,
262 280 dfs_info_t *referrals)
263 281 {
264 282 _NOTE(ARGUNUSED(sr))
265 283 uint16_t entsize, rep_bufsize;
266 284 uint16_t server_type;
267 285 uint16_t flags = 0;
268 286 uint16_t r;
269 287 char *target;
270 288
271 289 rep_bufsize = MBC_MAXBYTES(mbc);
272 290
273 291 server_type = (referrals->i_type == DFS_OBJECT_ROOT) ?
274 292 DFS_SRVTYPE_ROOT : DFS_SRVTYPE_NONROOT;
275 293
276 294 target = kmem_alloc(MAXPATHLEN, KM_SLEEP);
277 295
278 296 for (r = 0; r < referrals->i_ntargets; r++) {
279 297 (void) snprintf(target, MAXPATHLEN, "\\%s\\%s",
280 298 referrals->i_targets[r].t_server,
281 299 referrals->i_targets[r].t_share);
282 300
283 301 entsize = DFS_REFV1_ENTSZ + smb_wcequiv_strlen(target) + 2;
284 302 if (entsize > rep_bufsize)
285 303 break;
286 304
287 305 (void) smb_mbc_encodef(mbc, "wwwwU",
288 306 DFS_REFERRAL_V1, entsize, server_type, flags, target);
289 307 rep_bufsize -= entsize;
290 308 }
291 309
292 310 kmem_free(target, MAXPATHLEN);
293 311
294 312 /*
295 313 * Need room for at least one entry.
296 314 * Windows will silently drop targets that do not fit in
297 315 * the response buffer.
298 316 */
299 317 if (r == 0) {
300 318 return (NT_STATUS_BUFFER_OVERFLOW);
301 319 }
302 320
303 321 return (NT_STATUS_SUCCESS);
304 322 }
305 323
306 324 /*
307 325 * Prepare a response with V2 referral format.
308 326 *
309 327 * Here is the response packet format.
310 328 * All the strings come after all the fixed size entry headers.
311 329 * These headers contain offsets to the strings at the end. Note
312 330 * that the two "dfs_path" after the last entry is shared between
313 331 * all the entries.
314 332 *
315 333 * ent1-hdr
316 334 * ent2-hdr
317 335 * ...
318 336 * entN-hdr
319 337 * dfs_path
320 338 * dfs_path
321 339 * target1
322 340 * target2
323 341 * ...
324 342 * targetN
325 343 *
326 344 * MS-DFSC mentions that strings can come after each entry header or all after
327 345 * the last entry header. Windows responses are in the format above.
328 346 */
329 347 static uint32_t
330 348 smb_dfs_encode_refv2(smb_request_t *sr, mbuf_chain_t *mbc,
331 349 dfs_info_t *referrals)
332 350 {
333 351 _NOTE(ARGUNUSED(sr))
334 352 uint16_t entsize, rep_bufsize;
335 353 uint16_t server_type;
336 354 uint16_t flags = 0;
337 355 uint32_t proximity = 0;
338 356 uint16_t path_offs, altpath_offs, netpath_offs;
339 357 uint16_t targetsz, total_targetsz = 0;
340 358 uint16_t dfs_pathsz;
341 359 uint16_t r;
342 360
343 361 rep_bufsize = MBC_MAXBYTES(mbc);
344 362 dfs_pathsz = smb_wcequiv_strlen(referrals->i_uncpath) + 2;
345 363 entsize = DFS_REFV2_ENTSZ + dfs_pathsz + dfs_pathsz +
346 364 smb_dfs_referrals_unclen(referrals, 0);
347 365
348 366 if (entsize > rep_bufsize) {
349 367 /* need room for at least one referral */
350 368 return (NT_STATUS_BUFFER_OVERFLOW);
351 369 }
352 370
353 371 server_type = (referrals->i_type == DFS_OBJECT_ROOT) ?
354 372 DFS_SRVTYPE_ROOT : DFS_SRVTYPE_NONROOT;
355 373
356 374 rep_bufsize -= entsize;
357 375 entsize = DFS_REFV2_ENTSZ;
358 376
359 377 for (r = 0; r < referrals->i_ntargets; r++) {
360 378 path_offs = (referrals->i_ntargets - r) * DFS_REFV2_ENTSZ;
361 379 altpath_offs = path_offs + dfs_pathsz;
362 380 netpath_offs = altpath_offs + dfs_pathsz + total_targetsz;
363 381 targetsz = smb_dfs_referrals_unclen(referrals, r);
364 382
365 383 if (r != 0) {
366 384 entsize = DFS_REFV2_ENTSZ + targetsz;
367 385 if (entsize > rep_bufsize)
368 386 /* silently drop targets that do not fit */
369 387 break;
370 388 rep_bufsize -= entsize;
371 389 }
372 390
373 391 (void) smb_mbc_encodef(mbc, "wwwwllwww",
374 392 DFS_REFERRAL_V2, DFS_REFV2_ENTSZ, server_type, flags,
375 393 proximity, referrals->i_timeout, path_offs, altpath_offs,
376 394 netpath_offs);
377 395
378 396 total_targetsz += targetsz;
379 397 }
380 398
381 399 smb_dfs_encode_targets(mbc, referrals);
382 400
383 401 return (NT_STATUS_SUCCESS);
|
↓ open down ↓ |
239 lines elided |
↑ open up ↑ |
384 402 }
385 403
386 404 /*
387 405 * Prepare a response with V3/V4 referral format.
388 406 *
389 407 * For more details, see comments for smb_dfs_encode_refv2() or see
390 408 * MS-DFSC specification.
391 409 */
392 410 static uint32_t
393 411 smb_dfs_encode_refv3x(smb_request_t *sr, mbuf_chain_t *mbc,
394 - dfs_info_t *referrals,
395 - uint16_t ver)
412 + dfs_info_t *referrals, uint16_t ver)
396 413 {
397 414 _NOTE(ARGUNUSED(sr))
398 415 uint16_t entsize, rep_bufsize, hdrsize;
399 416 uint16_t server_type;
400 417 uint16_t flags = 0;
401 418 uint16_t path_offs, altpath_offs, netpath_offs;
402 419 uint16_t targetsz, total_targetsz = 0;
403 420 uint16_t dfs_pathsz;
404 421 uint16_t r;
405 422
406 423 hdrsize = (ver == DFS_REFERRAL_V3) ? DFS_REFV3_ENTSZ : DFS_REFV4_ENTSZ;
407 424 rep_bufsize = MBC_MAXBYTES(mbc);
408 425 dfs_pathsz = smb_wcequiv_strlen(referrals->i_uncpath) + 2;
409 426 entsize = hdrsize + dfs_pathsz + dfs_pathsz +
410 427 smb_dfs_referrals_unclen(referrals, 0);
411 428
412 429 if (entsize > rep_bufsize) {
413 430 /* need room for at least one referral */
414 431 return (NT_STATUS_BUFFER_OVERFLOW);
415 432 }
416 433
417 434 server_type = (referrals->i_type == DFS_OBJECT_ROOT) ?
418 435 DFS_SRVTYPE_ROOT : DFS_SRVTYPE_NONROOT;
419 436
420 437 rep_bufsize -= entsize;
421 438
422 439 for (r = 0; r < referrals->i_ntargets; r++) {
423 440 path_offs = (referrals->i_ntargets - r) * hdrsize;
424 441 altpath_offs = path_offs + dfs_pathsz;
425 442 netpath_offs = altpath_offs + dfs_pathsz + total_targetsz;
426 443 targetsz = smb_dfs_referrals_unclen(referrals, r);
427 444
428 445 if (r != 0) {
429 446 entsize = hdrsize + targetsz;
430 447 if (entsize > rep_bufsize)
431 448 /* silently drop targets that do not fit */
432 449 break;
433 450 rep_bufsize -= entsize;
434 451 flags = 0;
435 452 } else if (ver == DFS_REFERRAL_V4) {
436 453 flags = DFS_ENTFLG_T;
437 454 }
438 455
439 456 (void) smb_mbc_encodef(mbc, "wwwwlwww16.",
440 457 ver, hdrsize, server_type, flags,
441 458 referrals->i_timeout, path_offs, altpath_offs,
442 459 netpath_offs);
443 460
444 461 total_targetsz += targetsz;
445 462 }
446 463
447 464 smb_dfs_encode_targets(mbc, referrals);
448 465
449 466 return (NT_STATUS_SUCCESS);
450 467 }
451 468
452 469 /*
453 470 * Encodes DFS path, and target strings which come after fixed header
454 471 * entries.
455 472 *
456 473 * Windows 2000 and earlier set the DFSAlternatePathOffset to point to
457 474 * an 8.3 string representation of the string pointed to by
458 475 * DFSPathOffset if it is not a legal 8.3 string. Otherwise, if
459 476 * DFSPathOffset points to a legal 8.3 string, DFSAlternatePathOffset
460 477 * points to a separate copy of the same string. Windows Server 2003,
461 478 * Windows Server 2008 and Windows Server 2008 R2 set the
462 479 * DFSPathOffset and DFSAlternatePathOffset fields to point to separate
463 480 * copies of the identical string.
464 481 *
465 482 * Following Windows 2003 and later here.
466 483 */
467 484 static void
468 485 smb_dfs_encode_targets(mbuf_chain_t *mbc, dfs_info_t *referrals)
469 486 {
470 487 char *target;
471 488 int r;
472 489
473 490 (void) smb_mbc_encodef(mbc, "UU", referrals->i_uncpath,
474 491 referrals->i_uncpath);
475 492
476 493 target = kmem_alloc(MAXPATHLEN, KM_SLEEP);
477 494 for (r = 0; r < referrals->i_ntargets; r++) {
478 495 (void) snprintf(target, MAXPATHLEN, "\\%s\\%s",
479 496 referrals->i_targets[r].t_server,
480 497 referrals->i_targets[r].t_share);
481 498 (void) smb_mbc_encodef(mbc, "U", target);
482 499 }
483 500 kmem_free(target, MAXPATHLEN);
484 501 }
485 502
486 503 /*
487 504 * Get referral information for the specified path from user space
488 505 * using a door call.
489 506 */
490 507 static uint32_t
491 508 smb_dfs_referrals_get(smb_request_t *sr, char *dfs_path, dfs_reftype_t reftype,
492 509 dfs_referral_response_t *refrsp)
493 510 {
494 511 dfs_referral_query_t req;
495 512 int rc;
496 513
|
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
497 514 req.rq_type = reftype;
498 515 req.rq_path = dfs_path;
499 516
500 517 bzero(refrsp, sizeof (dfs_referral_response_t));
501 518 refrsp->rp_status = NT_STATUS_NOT_FOUND;
502 519
503 520 rc = smb_kdoor_upcall(sr->sr_server, SMB_DR_DFS_GET_REFERRALS,
504 521 &req, dfs_referral_query_xdr, refrsp, dfs_referral_response_xdr);
505 522
506 523 if (rc != 0 || refrsp->rp_status != ERROR_SUCCESS) {
507 - return (NT_STATUS_NO_SUCH_DEVICE);
524 + return (NT_STATUS_FS_DRIVER_REQUIRED);
508 525 }
509 526
510 527 (void) strsubst(refrsp->rp_referrals.i_uncpath, '/', '\\');
511 528 return (NT_STATUS_SUCCESS);
512 529 }
513 530
514 531 static void
515 532 smb_dfs_referrals_free(dfs_referral_response_t *refrsp)
516 533 {
517 534 xdr_free(dfs_referral_response_xdr, (char *)refrsp);
518 535 }
519 536
520 537 /*
521 538 * Returns the Unicode string length for the target UNC of
522 539 * the specified entry by 'refno'
523 540 *
524 541 * Note that the UNC path should be encoded with ONE leading
525 542 * slash not two as is common to user-visible UNC paths.
526 543 */
527 544 static uint16_t
528 545 smb_dfs_referrals_unclen(dfs_info_t *referrals, uint16_t refno)
529 546 {
530 547 uint16_t len;
531 548
532 549 if (refno >= referrals->i_ntargets)
533 550 return (0);
534 551
535 552 /* Encoded target UNC \server\share */
536 553 len = smb_wcequiv_strlen(referrals->i_targets[refno].t_server) +
537 554 smb_wcequiv_strlen(referrals->i_targets[refno].t_share) +
538 555 smb_wcequiv_strlen("\\\\") + 2; /* two '\' + NULL */
539 556
540 557 return (len);
541 558 }
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX