1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Net DFS server side RPC service for managing DFS namespaces. 28 * 29 * For more details refer to following Microsoft specification: 30 * [MS-DFSNM] 31 * Distributed File System (DFS): Namespace Management Protocol Specification 32 */ 33 34 #include <unistd.h> 35 #include <libgen.h> 36 #include <strings.h> 37 #include <sys/sysmacros.h> 38 39 #include <smbsrv/libmlsvc.h> 40 #include <smbsrv/nmpipes.h> 41 #include <smbsrv/ndl/netdfs.ndl> 42 #include <dfs.h> 43 44 /* 45 * Depends on the information level requested around 4000 or more links 46 * can be provided with this buffer size. The limitation here is due 47 * to some problem in NDR and/or opipe layer so: 48 * 49 * - Do NOT increase the buffer size until that problem is fixed 50 * - The buffer size should be increased when the problem is fixed 51 * so the 4000 link limitation is removed. 52 */ 53 #define NETDFS_MAXBUFLEN (800 * 1024) 54 #define NETDFS_MAXPREFLEN ((uint32_t)(-1)) 55 56 typedef struct netdfs_enumhandle_t { 57 uint32_t de_level; /* level of detail being requested */ 58 uint32_t de_prefmaxlen; /* client MAX size buffer preference */ 59 uint32_t de_resume; /* client resume handle */ 60 uint32_t de_bavail; /* remaining buffer space in bytes */ 61 uint32_t de_ntotal; /* total number of objects */ 62 uint32_t de_nmax; /* MAX number of objects to return */ 63 uint32_t de_nitems; /* number of objects in buf */ 64 uint32_t de_nskip; /* number of objects to skip */ 65 void *de_entries; /* ndr buffer */ 66 } netdfs_enumhandle_t; 67 68 static int netdfs_s_getver(void *, ndr_xa_t *); 69 static int netdfs_s_add(void *, ndr_xa_t *); 70 static int netdfs_s_remove(void *, ndr_xa_t *); 71 static int netdfs_s_setinfo(void *, ndr_xa_t *); 72 static int netdfs_s_getinfo(void *, ndr_xa_t *); 73 static int netdfs_s_enum(void *, ndr_xa_t *); 74 static int netdfs_s_move(void *, ndr_xa_t *); 75 static int netdfs_s_rename(void *, ndr_xa_t *); 76 static int netdfs_s_addstdroot(void *, ndr_xa_t *); 77 static int netdfs_s_remstdroot(void *, ndr_xa_t *); 78 static int netdfs_s_enumex(void *, ndr_xa_t *); 79 80 static uint32_t netdfs_setinfo_100(dfs_path_t *, netdfs_info100_t *); 81 static uint32_t netdfs_setinfo_101(dfs_path_t *, netdfs_info101_t *, 82 const char *, const char *); 83 static uint32_t netdfs_setinfo_102(dfs_path_t *, netdfs_info102_t *); 84 static uint32_t netdfs_setinfo_103(dfs_path_t *, netdfs_info103_t *); 85 static uint32_t netdfs_setinfo_104(dfs_path_t *, netdfs_info104_t *, 86 const char *, const char *); 87 static uint32_t netdfs_setinfo_105(dfs_path_t *, netdfs_info105_t *); 88 89 static uint32_t netdfs_info_1(netdfs_info1_t *, dfs_info_t *, ndr_xa_t *, 90 uint32_t *); 91 static uint32_t netdfs_info_2(netdfs_info2_t *, dfs_info_t *, ndr_xa_t *, 92 uint32_t *); 93 static uint32_t netdfs_info_3(netdfs_info3_t *, dfs_info_t *, ndr_xa_t *, 94 uint32_t *); 95 static uint32_t netdfs_info_4(netdfs_info4_t *, dfs_info_t *, ndr_xa_t *, 96 uint32_t *); 97 static uint32_t netdfs_info_5(netdfs_info5_t *, dfs_info_t *, ndr_xa_t *, 98 uint32_t *); 99 static uint32_t netdfs_info_6(netdfs_info6_t *, dfs_info_t *, ndr_xa_t *, 100 uint32_t *); 101 static uint32_t netdfs_info_100(netdfs_info100_t *, dfs_info_t *, ndr_xa_t *, 102 uint32_t *); 103 static uint32_t netdfs_info_300(netdfs_info300_t *, dfs_info_t *, ndr_xa_t *, 104 uint32_t *); 105 106 static uint32_t netdfs_enum_common(netdfs_enumhandle_t *, ndr_xa_t *); 107 108 static void netdfs_path_create(const char *); 109 static void netdfs_path_remove(smb_unc_t *); 110 static boolean_t netdfs_guid_fromstr(char *, netdfs_uuid_t *); 111 112 static ndr_stub_table_t netdfs_stub_table[] = { 113 { netdfs_s_getver, NETDFS_OPNUM_GETVER }, 114 { netdfs_s_add, NETDFS_OPNUM_ADD }, 115 { netdfs_s_remove, NETDFS_OPNUM_REMOVE }, 116 { netdfs_s_setinfo, NETDFS_OPNUM_SETINFO }, 117 { netdfs_s_getinfo, NETDFS_OPNUM_GETINFO }, 118 { netdfs_s_enum, NETDFS_OPNUM_ENUM }, 119 { netdfs_s_rename, NETDFS_OPNUM_RENAME }, 120 { netdfs_s_move, NETDFS_OPNUM_MOVE }, 121 { netdfs_s_addstdroot, NETDFS_OPNUM_ADDSTDROOT }, 122 { netdfs_s_remstdroot, NETDFS_OPNUM_REMSTDROOT }, 123 { netdfs_s_enumex, NETDFS_OPNUM_ENUMEX }, 124 {0} 125 }; 126 127 static ndr_service_t netdfs_service = { 128 "NETDFS", /* name */ 129 "DFS", /* desc */ 130 "\\netdfs", /* endpoint */ 131 PIPE_NETDFS, /* sec_addr_port */ 132 NETDFS_ABSTRACT_UUID, NETDFS_ABSTRACT_VERS, 133 NETDFS_TRANSFER_UUID, NETDFS_TRANSFER_VERS, 134 135 0, /* no bind_instance_size */ 136 0, /* no bind_req() */ 137 0, /* no unbind_and_close() */ 138 0, /* use generic_call_stub() */ 139 140 &TYPEINFO(netdfs_interface), /* interface ti */ 141 netdfs_stub_table /* stub_table */ 142 }; 143 144 /* 145 * Register the NETDFS RPC interface with the RPC runtime library. 146 * The service must be registered in order to use either the client 147 * side or the server side functions. 148 */ 149 void 150 netdfs_initialize(void) 151 { 152 (void) ndr_svc_register(&netdfs_service); 153 dfs_init(); 154 } 155 156 void 157 netdfs_finalize(void) 158 { 159 dfs_fini(); 160 } 161 162 /* 163 * Returns the version number of the DFS server in use on the server. 164 * 165 * [MS-DFSNM]: NetrDfsManagerGetVersion (Opnum 0) 166 */ 167 /*ARGSUSED*/ 168 static int 169 netdfs_s_getver(void *arg, ndr_xa_t *mxa) 170 { 171 struct netdfs_getver *param = arg; 172 173 param->version = DFS_MANAGER_VERSION_NT4; 174 return (NDR_DRC_OK); 175 } 176 177 /* 178 * Creates a new DFS link or adds a new target to an existing link of a 179 * DFS namespace. 180 * 181 * [MS-DFSNM]: NetrDfsAdd (Opnum 1) 182 */ 183 static int 184 netdfs_s_add(void *arg, ndr_xa_t *mxa) 185 { 186 netdfs_add_t *param = arg; 187 dfs_path_t path; 188 uint32_t status; 189 const char *uncpath = (const char *)param->dfs_path; 190 const char *fspath = (const char *)path.p_fspath; 191 boolean_t newlink; 192 193 if (!ndr_is_admin(mxa)) { 194 param->status = ERROR_ACCESS_DENIED; 195 return (NDR_DRC_OK); 196 } 197 198 if (param->server == NULL || param->share == NULL) { 199 param->status = ERROR_INVALID_PARAMETER; 200 return (NDR_DRC_OK); 201 } 202 203 switch (param->flags) { 204 case DFS_CREATE_VOLUME: 205 case DFS_ADD_VOLUME: 206 case DFS_RESTORE_VOLUME: 207 case (DFS_ADD_VOLUME | DFS_RESTORE_VOLUME): 208 break; 209 default: 210 param->status = ERROR_INVALID_PARAMETER; 211 return (NDR_DRC_OK); 212 } 213 214 status = dfs_path_parse(&path, uncpath, DFS_OBJECT_LINK); 215 if (status != ERROR_SUCCESS) { 216 param->status = status; 217 return (NDR_DRC_OK); 218 } 219 220 status = smb_name_validate_rpath(path.p_unc.unc_path); 221 if (status != ERROR_SUCCESS) { 222 dfs_path_free(&path); 223 param->status = status; 224 return (NDR_DRC_OK); 225 } 226 227 dfs_setpriv(PRIV_ON); 228 229 netdfs_path_create(fspath); 230 231 status = dfs_link_add(fspath, (const char *)param->server, 232 (const char *)param->share, (const char *)param->comment, 233 param->flags, &newlink); 234 235 if (newlink) 236 (void) dfs_cache_add_byname(path.p_unc.unc_share, 237 path.p_unc.unc_path, DFS_OBJECT_LINK); 238 239 if (status != ERROR_SUCCESS) 240 netdfs_path_remove(&path.p_unc); 241 242 dfs_setpriv(PRIV_OFF); 243 244 dfs_path_free(&path); 245 param->status = status; 246 return (NDR_DRC_OK); 247 } 248 249 /* 250 * Removes a link or a link target from a DFS namespace. A link can be 251 * removed regardless of the number of targets associated with it. 252 * 253 * [MS-DFSNM]: NetrDfsRemove (Opnum 2) 254 */ 255 static int 256 netdfs_s_remove(void *arg, ndr_xa_t *mxa) 257 { 258 struct netdfs_remove *param = arg; 259 dfs_path_t path; 260 uint32_t status, stat; 261 const char *uncpath = (const char *)param->dfs_path; 262 const char *fspath = (const char *)path.p_fspath; 263 264 if (!ndr_is_admin(mxa)) { 265 param->status = ERROR_ACCESS_DENIED; 266 return (NDR_DRC_OK); 267 } 268 269 /* both server and share must be NULL or non-NULL */ 270 if ((param->server == NULL && param->share != NULL) || 271 (param->server != NULL && param->share == NULL)) { 272 param->status = ERROR_INVALID_PARAMETER; 273 return (NDR_DRC_OK); 274 } 275 276 status = dfs_path_parse(&path, uncpath, DFS_OBJECT_LINK); 277 if (status != ERROR_SUCCESS) { 278 param->status = status; 279 return (NDR_DRC_OK); 280 } 281 282 dfs_setpriv(PRIV_ON); 283 284 status = dfs_link_remove(fspath, (const char *)param->server, 285 (const char *)param->share); 286 287 if (status == ERROR_SUCCESS) { 288 if (dfs_link_stat(fspath, &stat) == ERROR_SUCCESS) { 289 if (stat != DFS_STAT_ISDFS) 290 dfs_cache_remove(path.p_unc.unc_share, 291 path.p_unc.unc_path); 292 /* 293 * if link is removed then try to remove its 294 * empty parent directories if any 295 */ 296 if (stat == DFS_STAT_NOTFOUND) 297 netdfs_path_remove(&path.p_unc); 298 } 299 } 300 301 dfs_setpriv(PRIV_OFF); 302 303 dfs_path_free(&path); 304 param->status = status; 305 return (NDR_DRC_OK); 306 } 307 308 /* 309 * Sets or modifies information relevant to a specific DFS root, DFS root 310 * target, DFS link, or DFS link target 311 * 312 * [MS-DFSNM]: NetrDfsSetInfo (Opnum 3) 313 */ 314 /*ARGSUSED*/ 315 static int 316 netdfs_s_setinfo(void *arg, ndr_xa_t *mxa) 317 { 318 netdfs_setinfo_t *param = arg; 319 dfs_path_t path; 320 uint32_t status, stat; 321 322 /* both server and share must be NULL or non-NULL */ 323 if ((param->server == NULL && param->share != NULL) || 324 (param->server != NULL && param->share == NULL)) { 325 param->status = ERROR_INVALID_PARAMETER; 326 return (NDR_DRC_OK); 327 } 328 329 status = dfs_path_parse(&path, (const char *)param->dfs_path, 330 DFS_OBJECT_ANY); 331 332 if (status != ERROR_SUCCESS) { 333 param->status = status; 334 return (NDR_DRC_OK); 335 } 336 337 dfs_setpriv(PRIV_ON); 338 status = dfs_link_stat((const char *)path.p_fspath, &stat); 339 340 if ((path.p_type == DFS_OBJECT_LINK) && (stat != DFS_STAT_ISDFS)) { 341 dfs_setpriv(PRIV_OFF); 342 dfs_path_free(&path); 343 param->status = ERROR_NOT_FOUND; 344 return (NDR_DRC_OK); 345 } 346 347 switch (param->info.level) { 348 case 100: 349 status = netdfs_setinfo_100(&path, param->info.iu.info100); 350 break; 351 case 101: 352 status = netdfs_setinfo_101(&path, param->info.iu.info101, 353 (const char *)param->server, (const char *)param->share); 354 break; 355 case 102: 356 status = netdfs_setinfo_102(&path, param->info.iu.info102); 357 break; 358 case 103: 359 status = netdfs_setinfo_103(&path, param->info.iu.info103); 360 break; 361 case 104: 362 status = netdfs_setinfo_104(&path, param->info.iu.info104, 363 (const char *)param->server, (const char *)param->share); 364 break; 365 case 105: 366 status = netdfs_setinfo_105(&path, param->info.iu.info105); 367 break; 368 default: 369 status = ERROR_INVALID_LEVEL; 370 break; 371 } 372 373 dfs_setpriv(PRIV_OFF); 374 dfs_path_free(&path); 375 param->status = status; 376 return (NDR_DRC_OK); 377 } 378 379 /* 380 * Returns information about a DFS root or a DFS link of the specified 381 * DFS namespace. 382 * 383 * [MS-DFSNM]: NetrDfsGetInfo (Opnum 4) 384 */ 385 static int 386 netdfs_s_getinfo(void *arg, ndr_xa_t *mxa) 387 { 388 netdfs_getinfo_t *param = arg; 389 netdfs_info1_t *info1; 390 netdfs_info2_t *info2; 391 netdfs_info3_t *info3; 392 netdfs_info4_t *info4; 393 netdfs_info5_t *info5; 394 netdfs_info6_t *info6; 395 netdfs_info100_t *info100; 396 dfs_info_t info; 397 dfs_path_t path; 398 uint32_t status, stat; 399 const char *fspath; 400 uint32_t level = param->level; 401 402 status = dfs_path_parse(&path, (const char *)param->dfs_path, 403 DFS_OBJECT_ANY); 404 405 if (status != ERROR_SUCCESS) 406 goto getinfo_error; 407 408 dfs_setpriv(PRIV_ON); 409 410 fspath = path.p_fspath; 411 if (path.p_type == DFS_OBJECT_LINK) { 412 status = dfs_link_stat(fspath, &stat); 413 if ((status != ERROR_SUCCESS) || (stat != DFS_STAT_ISDFS)) { 414 status = ERROR_NOT_FOUND; 415 goto getinfo_error; 416 } 417 418 status = dfs_link_getinfo(fspath, &info, param->level); 419 } else { 420 status = dfs_root_getinfo(fspath, &info, param->level); 421 } 422 423 if (status != ERROR_SUCCESS) 424 goto getinfo_error; 425 426 (void) strlcpy(info.i_uncpath, (char *)param->dfs_path, 427 sizeof (info.i_uncpath)); 428 429 dfs_info_trace("netdfs_s_getinfo", &info); 430 431 status = ERROR_NOT_ENOUGH_MEMORY; 432 433 switch (level) { 434 case 1: 435 if ((info1 = NDR_NEW(mxa, netdfs_info1_t)) != NULL) { 436 param->info.iu.info1 = info1; 437 status = netdfs_info_1(info1, &info, mxa, NULL); 438 } 439 break; 440 case 2: 441 if ((info2 = NDR_NEW(mxa, netdfs_info2_t)) != NULL) { 442 param->info.iu.info2 = info2; 443 status = netdfs_info_2(info2, &info, mxa, NULL); 444 } 445 break; 446 case 3: 447 if ((info3 = NDR_NEW(mxa, netdfs_info3_t)) != NULL) { 448 param->info.iu.info3 = info3; 449 status = netdfs_info_3(info3, &info, mxa, NULL); 450 } 451 break; 452 case 4: 453 if ((info4 = NDR_NEW(mxa, netdfs_info4_t)) != NULL) { 454 param->info.iu.info4 = info4; 455 status = netdfs_info_4(info4, &info, mxa, NULL); 456 } 457 break; 458 case 5: 459 if ((info5 = NDR_NEW(mxa, netdfs_info5_t)) != NULL) { 460 param->info.iu.info5 = info5; 461 status = netdfs_info_5(info5, &info, mxa, NULL); 462 } 463 break; 464 case 6: 465 if ((info6 = NDR_NEW(mxa, netdfs_info6_t)) != NULL) { 466 param->info.iu.info6 = info6; 467 status = netdfs_info_6(info6, &info, mxa, NULL); 468 } 469 break; 470 case 100: 471 if ((info100 = NDR_NEW(mxa, netdfs_info100_t)) != NULL) { 472 param->info.iu.info100 = info100; 473 status = netdfs_info_100(info100, &info, mxa, NULL); 474 } 475 break; 476 477 default: 478 status = ERROR_INVALID_LEVEL; 479 break; 480 } 481 482 dfs_info_free(&info); 483 484 getinfo_error: 485 dfs_setpriv(PRIV_OFF); 486 dfs_path_free(&path); 487 if (status != ERROR_SUCCESS) 488 bzero(param, sizeof (netdfs_getinfo_t)); 489 490 param->info.level = level; 491 param->status = status; 492 return (NDR_DRC_OK); 493 } 494 495 /* 496 * Enumerates the DFS root hosted on a server or the DFS links of the 497 * namespace hosted by a server. Depending on the information level, 498 * the targets of the root and links are also displayed. 499 * 500 * For unsupported levels, it should return ERROR_INVALID_LEVEL as 501 * Microsoft does for DFS server on Win2000 and NT. 502 * 503 * [MS-DFSNM]: NetrDfsEnum (Opnum 5) 504 */ 505 /*ARGSUSED*/ 506 static int 507 netdfs_s_enum(void *arg, ndr_xa_t *mxa) 508 { 509 netdfs_enum_t *param = arg; 510 netdfs_enumhandle_t de; 511 uint32_t level = param->level; 512 uint32_t status = ERROR_SUCCESS; 513 uint32_t nroot; 514 size_t entsize; 515 516 if (param->info == NULL) { 517 status = ERROR_INVALID_PARAMETER; 518 goto enum_error; 519 } 520 521 if ((nroot = dfs_namespace_count()) == 0) 522 status = ERROR_NOT_FOUND; 523 else if (nroot > 1) 524 status = ERROR_DEVICE_NOT_AVAILABLE; 525 526 if (status != ERROR_SUCCESS) 527 goto enum_error; 528 529 bzero(&de, sizeof (netdfs_enumhandle_t)); 530 de.de_level = level; 531 de.de_ntotal = dfs_cache_num(); 532 533 if (param->pref_max_len == NETDFS_MAXPREFLEN || 534 param->pref_max_len > NETDFS_MAXBUFLEN) 535 de.de_prefmaxlen = NETDFS_MAXBUFLEN; 536 else 537 de.de_prefmaxlen = param->pref_max_len; 538 539 de.de_bavail = de.de_prefmaxlen; 540 541 if (param->resume_handle != NULL) { 542 if (*param->resume_handle >= de.de_ntotal) { 543 status = ERROR_NO_MORE_ITEMS; 544 goto enum_error; 545 } 546 de.de_resume = *param->resume_handle; 547 de.de_nskip = de.de_resume; 548 *param->resume_handle = 0; 549 } 550 551 dfs_setpriv(PRIV_ON); 552 553 status = ERROR_NOT_ENOUGH_MEMORY; 554 555 switch (level) { 556 case 1: 557 entsize = sizeof (netdfs_info1_t); 558 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 559 de.de_entries = NDR_NEWN(mxa, netdfs_info1_t, de.de_nmax); 560 if (de.de_entries == NULL) 561 goto enum_error; 562 563 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 564 param->info->iu.info1->info1 = de.de_entries; 565 param->info->iu.info1->count = de.de_nitems; 566 } 567 break; 568 case 2: 569 entsize = sizeof (netdfs_info2_t); 570 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 571 de.de_entries = NDR_NEWN(mxa, netdfs_info2_t, de.de_nmax); 572 if (de.de_entries == NULL) 573 goto enum_error; 574 575 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 576 param->info->iu.info2->info2 = de.de_entries; 577 param->info->iu.info2->count = de.de_nitems; 578 } 579 break; 580 case 3: 581 entsize = sizeof (netdfs_info3_t) + 582 sizeof (netdfs_storage_info_t); 583 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 584 de.de_entries = NDR_NEWN(mxa, netdfs_info3_t, de.de_nmax); 585 if (de.de_entries == NULL) 586 goto enum_error; 587 588 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 589 param->info->iu.info3->info3 = de.de_entries; 590 param->info->iu.info3->count = de.de_nitems; 591 } 592 break; 593 case 4: 594 entsize = sizeof (netdfs_info4_t) + 595 sizeof (netdfs_storage_info_t); 596 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 597 de.de_entries = NDR_NEWN(mxa, netdfs_info4_t, de.de_nmax); 598 if (de.de_entries == NULL) 599 goto enum_error; 600 601 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 602 param->info->iu.info4->info4 = de.de_entries; 603 param->info->iu.info4->count = de.de_nitems; 604 } 605 break; 606 607 case 5: 608 entsize = sizeof (netdfs_info5_t); 609 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 610 de.de_entries = NDR_NEWN(mxa, netdfs_info5_t, de.de_nmax); 611 if (de.de_entries == NULL) 612 goto enum_error; 613 614 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 615 param->info->iu.info5->info5 = de.de_entries; 616 param->info->iu.info5->count = de.de_nitems; 617 } 618 break; 619 620 case 6: 621 entsize = sizeof (netdfs_info6_t) + 622 sizeof (netdfs_storage_info1_t); 623 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 624 de.de_entries = NDR_NEWN(mxa, netdfs_info6_t, de.de_nmax); 625 if (de.de_entries == NULL) 626 goto enum_error; 627 628 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 629 param->info->iu.info6->info6 = de.de_entries; 630 param->info->iu.info6->count = de.de_nitems; 631 } 632 break; 633 634 case 300: 635 entsize = sizeof (netdfs_info300_t); 636 de.de_nmax = MAX((de.de_prefmaxlen / entsize), 1); 637 de.de_entries = NDR_NEWN(mxa, netdfs_info300_t, de.de_nmax); 638 if (de.de_entries == NULL) 639 goto enum_error; 640 641 if ((status = netdfs_enum_common(&de, mxa)) == ERROR_SUCCESS) { 642 param->info->iu.info300->info300 = de.de_entries; 643 param->info->iu.info300->count = de.de_nitems; 644 } 645 break; 646 647 default: 648 status = ERROR_INVALID_PARAMETER; 649 break; 650 } 651 652 if ((status == ERROR_SUCCESS) && (param->resume_handle != NULL)) 653 *param->resume_handle = de.de_resume; 654 655 enum_error: 656 dfs_setpriv(PRIV_OFF); 657 param->status = status; 658 return (NDR_DRC_OK); 659 } 660 661 /* 662 * Renames or moves a DFS link 663 * 664 * Does not need to be supported for DFS version 1 665 * 666 * [MS-DFSNM]: NetrDfsMove (Opnum 6) 667 */ 668 /*ARGSUSED*/ 669 static int 670 netdfs_s_move(void *arg, ndr_xa_t *mxa) 671 { 672 struct netdfs_move *param = arg; 673 674 param->status = ERROR_NOT_SUPPORTED; 675 return (NDR_DRC_OK); 676 } 677 678 /* 679 * According to [MS-DFSNM] spec this operation (opnum 7) is not 680 * used over the wire. 681 */ 682 /*ARGSUSED*/ 683 static int 684 netdfs_s_rename(void *arg, ndr_xa_t *mxa) 685 { 686 struct netdfs_rename *param = arg; 687 688 param->status = ERROR_NOT_SUPPORTED; 689 return (NDR_DRC_OK); 690 } 691 692 /* 693 * Creates a new standalone DFS namespace 694 * 695 * [MS-DFSNM]: NetrDfsAddStdRoot (Opnum 12) 696 */ 697 /*ARGSUSED*/ 698 static int 699 netdfs_s_addstdroot(void *arg, ndr_xa_t *mxa) 700 { 701 struct netdfs_addstdroot *param = arg; 702 const char *share = (const char *)param->share; 703 const char *comment = (const char *)param->comment; 704 705 if (!ndr_is_admin(mxa)) { 706 param->status = ERROR_ACCESS_DENIED; 707 return (NDR_DRC_OK); 708 } 709 710 dfs_setpriv(PRIV_ON); 711 /* For now only allow a single standalone namespace */ 712 if (dfs_namespace_count() == 0) 713 param->status = dfs_namespace_add(share, comment); 714 else 715 param->status = ERROR_NOT_SUPPORTED; 716 dfs_setpriv(PRIV_OFF); 717 718 return (NDR_DRC_OK); 719 } 720 721 /* 722 * Deletes the specified stand-alone DFS namespace. The DFS namespace can be 723 * removed without first removing all of the links in it. 724 * 725 * [MS-DFSNM]: NetrDfsRemoveStdRoot (Opnum 13) 726 */ 727 /*ARGSUSED*/ 728 static int 729 netdfs_s_remstdroot(void *arg, ndr_xa_t *mxa) 730 { 731 struct netdfs_remstdroot *param = arg; 732 const char *share = (const char *)param->share; 733 734 dfs_setpriv(PRIV_ON); 735 736 if (ndr_is_admin(mxa)) 737 param->status = dfs_namespace_remove(share); 738 else 739 param->status = ERROR_ACCESS_DENIED; 740 741 dfs_setpriv(PRIV_OFF); 742 return (NDR_DRC_OK); 743 } 744 745 /* 746 * Enumerates the DFS roots hosted on a server, or DFS links of a namespace 747 * hosted by the server. Depending on the information level, the targets 748 * associated with the roots and links are also displayed 749 * 750 * Does not need to be supported for DFS version 1 751 * 752 * [MS-DFSNM] NetrDfsEnumEx (Opnum 21) 753 */ 754 /*ARGSUSED*/ 755 static int 756 netdfs_s_enumex(void *arg, ndr_xa_t *mxa) 757 { 758 struct netdfs_enumex *param = arg; 759 760 bzero(param->info, sizeof (struct netdfs_enumex)); 761 param->status = ERROR_NOT_SUPPORTED; 762 return (NDR_DRC_OK); 763 } 764 765 /* 766 * Sets the comment for the DFS link/root. 767 */ 768 static uint32_t 769 netdfs_setinfo_100(dfs_path_t *path, netdfs_info100_t *netinfo) 770 { 771 dfs_info_t info; 772 uint32_t status; 773 char *cmnt = (char *)netinfo->comment; 774 775 bzero(&info, sizeof (dfs_info_t)); 776 if (cmnt != NULL) 777 (void) strlcpy(info.i_comment, cmnt, sizeof (info.i_comment)); 778 779 if (path->p_type == DFS_OBJECT_LINK) 780 status = dfs_link_setinfo(path->p_fspath, &info, 100); 781 else 782 status = dfs_root_setinfo(path->p_fspath, &info, 100); 783 784 return (status); 785 } 786 787 /* 788 * Sets the state for the DFS root/link or its target. 789 */ 790 static uint32_t 791 netdfs_setinfo_101(dfs_path_t *path, netdfs_info101_t *netinfo, 792 const char *t_server, const char *t_share) 793 { 794 dfs_info_t info; 795 dfs_target_t target; 796 uint32_t status; 797 798 bzero(&info, sizeof (dfs_info_t)); 799 bzero(&target, sizeof (dfs_target_t)); 800 801 if (t_server == NULL && t_share == NULL) { 802 info.i_state = netinfo->state; 803 } else { 804 target.t_state = netinfo->state; 805 (void) strlcpy(target.t_server, t_server, 806 sizeof (target.t_server)); 807 (void) strlcpy(target.t_share, t_share, 808 sizeof (target.t_share)); 809 info.i_targets = ⌖ 810 } 811 812 if (path->p_type == DFS_OBJECT_LINK) 813 status = dfs_link_setinfo(path->p_fspath, &info, 101); 814 else 815 status = dfs_root_setinfo(path->p_fspath, &info, 101); 816 817 return (status); 818 } 819 820 /* 821 * Sets the timeout value of the DFS link/root. 822 */ 823 static uint32_t 824 netdfs_setinfo_102(dfs_path_t *path, netdfs_info102_t *netinfo) 825 { 826 dfs_info_t info; 827 uint32_t status; 828 829 bzero(&info, sizeof (dfs_info_t)); 830 info.i_timeout = netinfo->timeout; 831 832 if (path->p_type == DFS_OBJECT_LINK) 833 status = dfs_link_setinfo(path->p_fspath, &info, 102); 834 else 835 status = dfs_root_setinfo(path->p_fspath, &info, 102); 836 837 return (status); 838 } 839 840 /* 841 * Sets the property flags for the root or link. 842 */ 843 static uint32_t 844 netdfs_setinfo_103(dfs_path_t *path, netdfs_info103_t *netinfo) 845 { 846 dfs_info_t info; 847 uint32_t status; 848 849 bzero(&info, sizeof (dfs_info_t)); 850 info.i_propflags = 851 netinfo->property_flags & netinfo->property_flag_mask; 852 853 if (path->p_type == DFS_OBJECT_LINK) 854 status = dfs_link_setinfo(path->p_fspath, &info, 103); 855 else 856 status = dfs_root_setinfo(path->p_fspath, &info, 103); 857 858 return (status); 859 } 860 861 /* 862 * Sets the target priority rank and class for the root target or link target 863 */ 864 static uint32_t 865 netdfs_setinfo_104(dfs_path_t *path, netdfs_info104_t *netinfo, 866 const char *t_server, const char *t_share) 867 { 868 dfs_info_t info; 869 dfs_target_t target; 870 uint32_t status; 871 872 if ((t_server == NULL) || (t_share == NULL)) 873 return (ERROR_INVALID_PARAMETER); 874 875 if (netinfo->priority_class > DfsGlobalLowPriorityClass) 876 return (ERROR_INVALID_PARAMETER); 877 878 if (netinfo->priority_rank > DFS_PRIORITY_RANK_MAX) 879 return (ERROR_INVALID_PARAMETER); 880 881 bzero(&info, sizeof (dfs_info_t)); 882 bzero(&target, sizeof (dfs_target_t)); 883 884 target.t_priority.p_class = netinfo->priority_class; 885 target.t_priority.p_rank = netinfo->priority_rank; 886 (void) strlcpy(target.t_server, t_server, sizeof (target.t_server)); 887 (void) strlcpy(target.t_share, t_share, sizeof (target.t_share)); 888 info.i_targets = ⌖ 889 890 if (path->p_type == DFS_OBJECT_LINK) 891 status = dfs_link_setinfo(path->p_fspath, &info, 104); 892 else 893 status = dfs_root_setinfo(path->p_fspath, &info, 104); 894 895 return (status); 896 } 897 898 /* 899 * Sets the comment, state, time-out information, and property flags for the 900 * namespace root or link specified in DfsInfo. Does not apply to a root target 901 * or link target. 902 */ 903 static uint32_t 904 netdfs_setinfo_105(dfs_path_t *path, netdfs_info105_t *netinfo) 905 { 906 dfs_info_t info; 907 uint32_t status, flavor; 908 char *cmnt = (char *)netinfo->comment; 909 910 bzero(&info, sizeof (dfs_info_t)); 911 912 flavor = dfs_namespace_getflavor(path->p_unc.unc_share); 913 if (flavor == 0) 914 return (ERROR_INTERNAL_ERROR); 915 info.i_flavor = flavor; 916 917 if (cmnt != NULL) 918 (void) strlcpy(info.i_comment, cmnt, sizeof (info.i_comment)); 919 info.i_state = netinfo->state; 920 info.i_timeout = netinfo->timeout; 921 info.i_propflag_mask = netinfo->property_flag_mask; 922 info.i_propflags = 923 netinfo->property_flags & netinfo->property_flag_mask; 924 925 if (path->p_type == DFS_OBJECT_LINK) 926 status = dfs_link_setinfo(path->p_fspath, &info, 105); 927 else 928 status = dfs_root_setinfo(path->p_fspath, &info, 105); 929 930 return (status); 931 } 932 933 /* 934 * DFS_STORAGE_INFO: target information 935 */ 936 static uint32_t 937 netdfs_info_storage(netdfs_storage_info_t **sinfo, dfs_info_t *info, 938 ndr_xa_t *mxa, uint32_t *size) 939 { 940 netdfs_storage_info_t *storage; 941 dfs_target_t *target; 942 int i; 943 944 *sinfo = NULL; 945 if (info->i_ntargets == 0) 946 return (ERROR_SUCCESS); 947 948 *sinfo = NDR_NEWN(mxa, netdfs_storage_info_t, info->i_ntargets); 949 if (*sinfo == NULL) 950 return (ERROR_NOT_ENOUGH_MEMORY); 951 952 if (size != NULL) 953 *size += info->i_ntargets * sizeof (netdfs_storage_info_t); 954 955 target = info->i_targets; 956 storage = *sinfo; 957 for (i = 0; i < info->i_ntargets; i++, target++, storage++) { 958 storage->state = target->t_state; 959 storage->server = NDR_STRDUP(mxa, target->t_server); 960 storage->share = NDR_STRDUP(mxa, target->t_share); 961 962 if (storage->server == NULL || storage->share == NULL) 963 return (ERROR_NOT_ENOUGH_MEMORY); 964 965 if (size != NULL) 966 *size += smb_wcequiv_strlen(target->t_server) + 967 smb_wcequiv_strlen(target->t_share); 968 } 969 970 return (ERROR_SUCCESS); 971 } 972 973 /* 974 * DFS_STORAGE_INFO_1: target information 975 */ 976 static uint32_t 977 netdfs_info_storage1(netdfs_storage_info1_t **sinfo, dfs_info_t *info, 978 ndr_xa_t *mxa, uint32_t *size) 979 { 980 netdfs_storage_info1_t *storage; 981 dfs_target_t *target; 982 int i; 983 984 *sinfo = NULL; 985 if (info->i_ntargets == 0) 986 return (ERROR_SUCCESS); 987 988 *sinfo = NDR_NEWN(mxa, netdfs_storage_info1_t, info->i_ntargets); 989 if (*sinfo == NULL) 990 return (ERROR_NOT_ENOUGH_MEMORY); 991 992 if (size != NULL) 993 *size += info->i_ntargets * sizeof (netdfs_storage_info1_t); 994 995 target = info->i_targets; 996 storage = *sinfo; 997 for (i = 0; i < info->i_ntargets; i++, target++, storage++) { 998 storage->state = target->t_state; 999 storage->server = NDR_STRDUP(mxa, target->t_server); 1000 storage->share = NDR_STRDUP(mxa, target->t_share); 1001 storage->p_class = target->t_priority.p_class; 1002 storage->p_rank = target->t_priority.p_rank; 1003 storage->p_reserved = 0; 1004 1005 if (storage->server == NULL || storage->share == NULL) 1006 return (ERROR_NOT_ENOUGH_MEMORY); 1007 1008 if (size != NULL) 1009 *size += smb_wcequiv_strlen(target->t_server) + 1010 smb_wcequiv_strlen(target->t_share); 1011 } 1012 1013 return (ERROR_SUCCESS); 1014 } 1015 1016 /* 1017 * Sets a DFS_INFO_1 for get/enum response 1018 */ 1019 static uint32_t 1020 netdfs_info_1(netdfs_info1_t *info1, dfs_info_t *info, ndr_xa_t *mxa, 1021 uint32_t *size) 1022 { 1023 info1->entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1024 if (info1->entry_path == NULL) 1025 return (ERROR_NOT_ENOUGH_MEMORY); 1026 1027 if (size != NULL) 1028 *size = sizeof (netdfs_info1_t) + 1029 smb_wcequiv_strlen(info->i_uncpath); 1030 1031 return (ERROR_SUCCESS); 1032 } 1033 1034 /* 1035 * Sets a DFS_INFO_2 for get/enum response 1036 */ 1037 static uint32_t 1038 netdfs_info_2(netdfs_info2_t *info2, dfs_info_t *info, ndr_xa_t *mxa, 1039 uint32_t *size) 1040 { 1041 void *entry_path; 1042 void *comment; 1043 1044 entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1045 comment = NDR_STRDUP(mxa, info->i_comment); 1046 1047 if (entry_path == NULL || comment == NULL) 1048 return (ERROR_NOT_ENOUGH_MEMORY); 1049 1050 info2->entry_path = entry_path; 1051 info2->comment = comment; 1052 info2->state = info->i_state; 1053 info2->n_store = info->i_ntargets; 1054 1055 if (size != NULL) 1056 *size = sizeof (netdfs_info2_t) + 1057 smb_wcequiv_strlen(info->i_uncpath) + 1058 smb_wcequiv_strlen(info->i_comment); 1059 1060 return (ERROR_SUCCESS); 1061 } 1062 1063 /* 1064 * Sets a DFS_INFO_3 for get/enum response 1065 */ 1066 static uint32_t 1067 netdfs_info_3(netdfs_info3_t *info3, dfs_info_t *info, ndr_xa_t *mxa, 1068 uint32_t *size) 1069 { 1070 void *entry_path; 1071 void *comment; 1072 1073 entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1074 comment = NDR_STRDUP(mxa, info->i_comment); 1075 1076 if (entry_path == NULL || comment == NULL) 1077 return (ERROR_NOT_ENOUGH_MEMORY); 1078 1079 info3->entry_path = entry_path; 1080 info3->comment = comment; 1081 info3->state = info->i_state; 1082 info3->n_store = info->i_ntargets; 1083 1084 if (size != NULL) 1085 *size = sizeof (netdfs_info3_t) + 1086 smb_wcequiv_strlen(info->i_uncpath) + 1087 smb_wcequiv_strlen(info->i_comment); 1088 1089 return (netdfs_info_storage(&info3->si, info, mxa, size)); 1090 } 1091 1092 /* 1093 * Sets a DFS_INFO_4 for get/enum response 1094 */ 1095 static uint32_t 1096 netdfs_info_4(netdfs_info4_t *info4, dfs_info_t *info, ndr_xa_t *mxa, 1097 uint32_t *size) 1098 { 1099 void *entry_path; 1100 void *comment; 1101 1102 entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1103 comment = NDR_STRDUP(mxa, info->i_comment); 1104 1105 if (entry_path == NULL || comment == NULL) 1106 return (ERROR_NOT_ENOUGH_MEMORY); 1107 1108 if (!netdfs_guid_fromstr(info->i_guid, &info4->guid)) 1109 return (ERROR_INVALID_DATA); 1110 1111 info4->entry_path = entry_path; 1112 info4->comment = comment; 1113 info4->state = info->i_state; 1114 info4->timeout = info->i_timeout; 1115 info4->n_store = info->i_ntargets; 1116 1117 if (size != NULL) 1118 *size = sizeof (netdfs_info4_t) + 1119 smb_wcequiv_strlen(info->i_uncpath) + 1120 smb_wcequiv_strlen(info->i_comment); 1121 1122 return (netdfs_info_storage(&info4->si, info, mxa, size)); 1123 } 1124 1125 /* 1126 * Sets a DFS_INFO_5 for get/enum response 1127 */ 1128 static uint32_t 1129 netdfs_info_5(netdfs_info5_t *info5, dfs_info_t *info, ndr_xa_t *mxa, 1130 uint32_t *size) 1131 { 1132 void *entry_path; 1133 void *comment; 1134 1135 entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1136 comment = NDR_STRDUP(mxa, info->i_comment); 1137 1138 if (entry_path == NULL || comment == NULL) 1139 return (ERROR_NOT_ENOUGH_MEMORY); 1140 1141 if (!netdfs_guid_fromstr(info->i_guid, &info5->guid)) 1142 return (ERROR_INVALID_DATA); 1143 1144 info5->entry_path = entry_path; 1145 info5->comment = comment; 1146 info5->state = info->i_state; 1147 info5->timeout = info->i_timeout; 1148 info5->flags = info->i_propflags; 1149 info5->metadata_sz = 0; 1150 info5->n_store = info->i_ntargets; 1151 1152 if (size != NULL) 1153 *size = sizeof (netdfs_info5_t) + 1154 smb_wcequiv_strlen(info->i_uncpath) + 1155 smb_wcequiv_strlen(info->i_comment); 1156 1157 return (ERROR_SUCCESS); 1158 } 1159 1160 /* 1161 * Sets a DFS_INFO_6 for get/enum response 1162 */ 1163 static uint32_t 1164 netdfs_info_6(netdfs_info6_t *info6, dfs_info_t *info, ndr_xa_t *mxa, 1165 uint32_t *size) 1166 { 1167 void *entry_path; 1168 void *comment; 1169 1170 entry_path = NDR_STRDUP(mxa, info->i_uncpath); 1171 comment = NDR_STRDUP(mxa, info->i_comment); 1172 1173 if (entry_path == NULL || comment == NULL) 1174 return (ERROR_NOT_ENOUGH_MEMORY); 1175 1176 if (!netdfs_guid_fromstr(info->i_guid, &info6->guid)) 1177 return (ERROR_INVALID_DATA); 1178 1179 info6->entry_path = entry_path; 1180 info6->comment = comment; 1181 info6->state = info->i_state; 1182 info6->timeout = info->i_timeout; 1183 info6->flags = info->i_propflags; 1184 info6->metadata_sz = 0; 1185 info6->n_store = info->i_ntargets; 1186 1187 if (size != NULL) 1188 *size = sizeof (netdfs_info6_t) + 1189 smb_wcequiv_strlen(info->i_uncpath) + 1190 smb_wcequiv_strlen(info->i_comment); 1191 1192 return (netdfs_info_storage1(&info6->si, info, mxa, size)); 1193 } 1194 1195 /* 1196 * Sets a DFS_INFO_100 for Get response 1197 */ 1198 static uint32_t 1199 netdfs_info_100(netdfs_info100_t *info100, dfs_info_t *info, ndr_xa_t *mxa, 1200 uint32_t *size) 1201 { 1202 info100->comment = NDR_STRDUP(mxa, info->i_comment); 1203 if (info100->comment == NULL) 1204 return (ERROR_NOT_ENOUGH_MEMORY); 1205 1206 if (size != NULL) 1207 *size = sizeof (netdfs_info100_t) + 1208 smb_wcequiv_strlen(info->i_comment); 1209 1210 return (ERROR_SUCCESS); 1211 } 1212 1213 /* 1214 * Sets a DFS_INFO_300 for Enum response 1215 */ 1216 static uint32_t 1217 netdfs_info_300(netdfs_info300_t *info300, dfs_info_t *info, ndr_xa_t *mxa, 1218 uint32_t *size) 1219 { 1220 info300->dfsname = NDR_STRDUP(mxa, info->i_uncpath); 1221 if (info300->dfsname == NULL) 1222 return (ERROR_NOT_ENOUGH_MEMORY); 1223 1224 info300->flavor = DFS_VOLUME_FLAVOR_STANDALONE; 1225 if (size != NULL) 1226 *size = sizeof (netdfs_info300_t) + 1227 smb_wcequiv_strlen(info->i_uncpath); 1228 1229 return (ERROR_SUCCESS); 1230 } 1231 1232 /* 1233 * Common enumeration function 1234 */ 1235 static uint32_t 1236 netdfs_enum_common(netdfs_enumhandle_t *de, ndr_xa_t *mxa) 1237 { 1238 netdfs_info1_t *info1 = de->de_entries; 1239 netdfs_info2_t *info2 = de->de_entries; 1240 netdfs_info3_t *info3 = de->de_entries; 1241 netdfs_info4_t *info4 = de->de_entries; 1242 netdfs_info5_t *info5 = de->de_entries; 1243 netdfs_info6_t *info6 = de->de_entries; 1244 netdfs_info300_t *info300 = de->de_entries; 1245 dfs_info_t dfsinfo; 1246 smb_cache_cursor_t cursor; 1247 dfs_nscnode_t nscnode; 1248 uint32_t status; 1249 uint32_t itemsz; 1250 1251 dfs_cache_iterinit(&cursor); 1252 1253 de->de_nitems = 0; 1254 while (dfs_cache_iterate(&cursor, &nscnode)) { 1255 if (de->de_nskip > 0) { 1256 de->de_nskip--; 1257 continue; 1258 } 1259 1260 if (de->de_nitems == de->de_nmax) 1261 break; 1262 1263 status = dfs_cache_getinfo(&nscnode, &dfsinfo, de->de_level); 1264 if (status != ERROR_SUCCESS) 1265 continue; 1266 1267 switch (de->de_level) { 1268 case 1: 1269 status = netdfs_info_1(info1, &dfsinfo, mxa, &itemsz); 1270 info1++; 1271 break; 1272 case 2: 1273 status = netdfs_info_2(info2, &dfsinfo, mxa, &itemsz); 1274 info2++; 1275 break; 1276 case 3: 1277 status = netdfs_info_3(info3, &dfsinfo, mxa, &itemsz); 1278 info3++; 1279 break; 1280 case 4: 1281 status = netdfs_info_4(info4, &dfsinfo, mxa, &itemsz); 1282 info4++; 1283 break; 1284 case 5: 1285 status = netdfs_info_5(info5, &dfsinfo, mxa, &itemsz); 1286 info5++; 1287 break; 1288 case 6: 1289 status = netdfs_info_6(info6, &dfsinfo, mxa, &itemsz); 1290 info6++; 1291 break; 1292 case 300: 1293 status = netdfs_info_300(info300, &dfsinfo, mxa, 1294 &itemsz); 1295 info300++; 1296 break; 1297 default: 1298 status = ERROR_INVALID_LEVEL; 1299 } 1300 1301 dfs_info_free(&dfsinfo); 1302 1303 if (status != ERROR_SUCCESS) 1304 return (status); 1305 1306 if (de->de_nmax == 1) { 1307 de->de_nitems = 1; 1308 break; 1309 } 1310 1311 if (itemsz > de->de_bavail) 1312 break; 1313 1314 de->de_bavail -= itemsz; 1315 de->de_nitems++; 1316 } 1317 1318 de->de_resume += de->de_nitems; 1319 return (ERROR_SUCCESS); 1320 } 1321 1322 /* 1323 * Creates intermediate directories of a link from the root share path. 1324 * 1325 * TODO: directories should be created by smbsrv to get Windows compatible 1326 * ACL inheritance. 1327 */ 1328 static void 1329 netdfs_path_create(const char *path) 1330 { 1331 char dirpath[DFS_PATH_MAX]; 1332 mode_t mode; 1333 char *p; 1334 1335 (void) strlcpy(dirpath, path, DFS_PATH_MAX); 1336 1337 /* drop the link itself from the path */ 1338 if ((p = strrchr(dirpath, '/')) != NULL) { 1339 *p = '\0'; 1340 mode = umask(0); 1341 (void) mkdirp(dirpath, 0777); 1342 (void) umask(mode); 1343 } 1344 } 1345 1346 /* 1347 * Removes empty directories 1348 */ 1349 static void 1350 netdfs_path_remove(smb_unc_t *unc) 1351 { 1352 char rootdir[DFS_PATH_MAX]; 1353 char relpath[DFS_PATH_MAX]; 1354 char dir[DFS_PATH_MAX]; 1355 uint32_t status; 1356 char *p; 1357 1358 status = dfs_namespace_path(unc->unc_share, rootdir, DFS_PATH_MAX); 1359 if ((status == ERROR_SUCCESS) && (chdir(rootdir) == 0)) { 1360 (void) strlcpy(relpath, unc->unc_path, DFS_PATH_MAX); 1361 /* drop the link itself from the path */ 1362 if ((p = strrchr(relpath, '/')) != NULL) { 1363 *p = '\0'; 1364 (void) rmdirp(relpath, dir); 1365 } 1366 } 1367 } 1368 1369 /* 1370 * Converts the guid string into binary format in network byte order. 1371 */ 1372 static boolean_t 1373 netdfs_guid_fromstr(char *guid_str, netdfs_uuid_t *guid) 1374 { 1375 uuid_t uuid; 1376 1377 if (uuid_parse(guid_str, uuid) != 0) 1378 return (B_FALSE); 1379 1380 bcopy(&uuid, guid, sizeof (uuid_t)); 1381 1382 guid->data1 = htonl(guid->data1); 1383 guid->data2 = htons(guid->data2); 1384 guid->data3 = htons(guid->data3); 1385 1386 return (B_TRUE); 1387 } 1388