1*da6c28aaSamw /* 2*da6c28aaSamw * CDDL HEADER START 3*da6c28aaSamw * 4*da6c28aaSamw * The contents of this file are subject to the terms of the 5*da6c28aaSamw * Common Development and Distribution License (the "License"). 6*da6c28aaSamw * You may not use this file except in compliance with the License. 7*da6c28aaSamw * 8*da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10*da6c28aaSamw * See the License for the specific language governing permissions 11*da6c28aaSamw * and limitations under the License. 12*da6c28aaSamw * 13*da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14*da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16*da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17*da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18*da6c28aaSamw * 19*da6c28aaSamw * CDDL HEADER END 20*da6c28aaSamw */ 21*da6c28aaSamw /* 22*da6c28aaSamw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*da6c28aaSamw * Use is subject to license terms. 24*da6c28aaSamw */ 25*da6c28aaSamw 26*da6c28aaSamw #pragma ident "%Z%%M% %I% %E% SMI" 27*da6c28aaSamw 28*da6c28aaSamw /* 29*da6c28aaSamw * Net DFS server side RPC service. 30*da6c28aaSamw */ 31*da6c28aaSamw 32*da6c28aaSamw #include <sys/types.h> 33*da6c28aaSamw #include <strings.h> 34*da6c28aaSamw #include <string.h> 35*da6c28aaSamw 36*da6c28aaSamw #include <smbsrv/libsmb.h> 37*da6c28aaSamw #include <smbsrv/lmerr.h> 38*da6c28aaSamw #include <smbsrv/lmdfs.h> 39*da6c28aaSamw #include <smbsrv/nmpipes.h> 40*da6c28aaSamw #include <smbsrv/nterror.h> 41*da6c28aaSamw #include <smbsrv/mlrpc.h> 42*da6c28aaSamw #include <smbsrv/ndl/netdfs.ndl> 43*da6c28aaSamw 44*da6c28aaSamw typedef struct { 45*da6c28aaSamw char *server; 46*da6c28aaSamw char *share; 47*da6c28aaSamw char *path; 48*da6c28aaSamw char *buf; 49*da6c28aaSamw } netdfs_unc_t; 50*da6c28aaSamw 51*da6c28aaSamw static int netdfs_unc_parse(struct mlrpc_xaction *, const char *, 52*da6c28aaSamw netdfs_unc_t *); 53*da6c28aaSamw 54*da6c28aaSamw static int netdfs_s_getver(void *, struct mlrpc_xaction *); 55*da6c28aaSamw static int netdfs_s_add(void *, struct mlrpc_xaction *); 56*da6c28aaSamw static int netdfs_s_remove(void *, struct mlrpc_xaction *); 57*da6c28aaSamw static int netdfs_s_setinfo(void *, struct mlrpc_xaction *); 58*da6c28aaSamw static int netdfs_s_getinfo(void *, struct mlrpc_xaction *); 59*da6c28aaSamw static int netdfs_s_enum(void *, struct mlrpc_xaction *); 60*da6c28aaSamw static int netdfs_s_move(void *, struct mlrpc_xaction *); 61*da6c28aaSamw static int netdfs_s_rename(void *, struct mlrpc_xaction *); 62*da6c28aaSamw static int netdfs_s_addstdroot(void *, struct mlrpc_xaction *); 63*da6c28aaSamw static int netdfs_s_remstdroot(void *, struct mlrpc_xaction *); 64*da6c28aaSamw static int netdfs_s_enumex(void *, struct mlrpc_xaction *); 65*da6c28aaSamw 66*da6c28aaSamw static mlrpc_stub_table_t netdfs_stub_table[] = { 67*da6c28aaSamw { netdfs_s_getver, NETDFS_OPNUM_GETVER }, 68*da6c28aaSamw { netdfs_s_add, NETDFS_OPNUM_ADD }, 69*da6c28aaSamw { netdfs_s_remove, NETDFS_OPNUM_REMOVE }, 70*da6c28aaSamw { netdfs_s_setinfo, NETDFS_OPNUM_SETINFO }, 71*da6c28aaSamw { netdfs_s_getinfo, NETDFS_OPNUM_GETINFO }, 72*da6c28aaSamw { netdfs_s_enum, NETDFS_OPNUM_ENUM }, 73*da6c28aaSamw { netdfs_s_rename, NETDFS_OPNUM_RENAME }, 74*da6c28aaSamw { netdfs_s_move, NETDFS_OPNUM_MOVE }, 75*da6c28aaSamw { netdfs_s_addstdroot, NETDFS_OPNUM_ADDSTDROOT }, 76*da6c28aaSamw { netdfs_s_remstdroot, NETDFS_OPNUM_REMSTDROOT }, 77*da6c28aaSamw { netdfs_s_enumex, NETDFS_OPNUM_ENUMEX }, 78*da6c28aaSamw {0} 79*da6c28aaSamw }; 80*da6c28aaSamw 81*da6c28aaSamw static mlrpc_service_t netdfs_service = { 82*da6c28aaSamw "NETDFS", /* name */ 83*da6c28aaSamw "DFS", /* desc */ 84*da6c28aaSamw "\\dfs", /* endpoint */ 85*da6c28aaSamw PIPE_NTSVCS, /* sec_addr_port */ 86*da6c28aaSamw NETDFS_ABSTRACT_UUID, NETDFS_ABSTRACT_VERS, 87*da6c28aaSamw NETDFS_TRANSFER_UUID, NETDFS_TRANSFER_VERS, 88*da6c28aaSamw 89*da6c28aaSamw 0, /* no bind_instance_size */ 90*da6c28aaSamw 0, /* no bind_req() */ 91*da6c28aaSamw 0, /* no unbind_and_close() */ 92*da6c28aaSamw 0, /* use generic_call_stub() */ 93*da6c28aaSamw 94*da6c28aaSamw &TYPEINFO(netdfs_interface), /* interface ti */ 95*da6c28aaSamw netdfs_stub_table /* stub_table */ 96*da6c28aaSamw }; 97*da6c28aaSamw 98*da6c28aaSamw /* 99*da6c28aaSamw * Register the NETDFS RPC interface with the RPC runtime library. 100*da6c28aaSamw * The service must be registered in order to use either the client 101*da6c28aaSamw * side or the server side functions. 102*da6c28aaSamw */ 103*da6c28aaSamw void 104*da6c28aaSamw netdfs_initialize(void) 105*da6c28aaSamw { 106*da6c28aaSamw (void) mlrpc_register_service(&netdfs_service); 107*da6c28aaSamw } 108*da6c28aaSamw 109*da6c28aaSamw /* 110*da6c28aaSamw * Return the version. 111*da6c28aaSamw * 112*da6c28aaSamw * We have to indicate that we emulate a Windows 2003 Server or the 113*da6c28aaSamw * client will not use the EnumEx RPC and this would limit support 114*da6c28aaSamw * to a single DFS root. 115*da6c28aaSamw */ 116*da6c28aaSamw /*ARGSUSED*/ 117*da6c28aaSamw static int 118*da6c28aaSamw netdfs_s_getver(void *arg, struct mlrpc_xaction *mxa) 119*da6c28aaSamw { 120*da6c28aaSamw struct netdfs_getver *param = arg; 121*da6c28aaSamw 122*da6c28aaSamw param->version = DFS_MANAGER_VERSION_W2K3; 123*da6c28aaSamw return (MLRPC_DRC_OK); 124*da6c28aaSamw } 125*da6c28aaSamw 126*da6c28aaSamw /* 127*da6c28aaSamw * Add a new volume or additional storage for an existing volume at 128*da6c28aaSamw * dfs_path. 129*da6c28aaSamw */ 130*da6c28aaSamw static int 131*da6c28aaSamw netdfs_s_add(void *arg, struct mlrpc_xaction *mxa) 132*da6c28aaSamw { 133*da6c28aaSamw struct netdfs_add *param = arg; 134*da6c28aaSamw netdfs_unc_t unc; 135*da6c28aaSamw DWORD status = ERROR_SUCCESS; 136*da6c28aaSamw 137*da6c28aaSamw if (param->dfs_path == NULL || param->server == NULL || 138*da6c28aaSamw param->share == NULL) { 139*da6c28aaSamw bzero(param, sizeof (struct netdfs_add)); 140*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 141*da6c28aaSamw return (MLRPC_DRC_OK); 142*da6c28aaSamw } 143*da6c28aaSamw 144*da6c28aaSamw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 145*da6c28aaSamw status = ERROR_INVALID_PARAMETER; 146*da6c28aaSamw } else { 147*da6c28aaSamw if (unc.path == NULL) 148*da6c28aaSamw status = ERROR_BAD_PATHNAME; 149*da6c28aaSamw 150*da6c28aaSamw if (unc.share == NULL) 151*da6c28aaSamw status = ERROR_INVALID_SHARENAME; 152*da6c28aaSamw } 153*da6c28aaSamw 154*da6c28aaSamw if (param->status != ERROR_SUCCESS) { 155*da6c28aaSamw bzero(param, sizeof (struct netdfs_add)); 156*da6c28aaSamw param->status = status; 157*da6c28aaSamw return (MLRPC_DRC_OK); 158*da6c28aaSamw } 159*da6c28aaSamw 160*da6c28aaSamw bzero(param, sizeof (struct netdfs_add)); 161*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 162*da6c28aaSamw return (MLRPC_DRC_OK); 163*da6c28aaSamw } 164*da6c28aaSamw 165*da6c28aaSamw /* 166*da6c28aaSamw * netdfs_s_remove 167*da6c28aaSamw * 168*da6c28aaSamw * Remove a volume or additional storage for volume from the DFS at 169*da6c28aaSamw * dfs_path. When applied to the last storage in a volume, removes 170*da6c28aaSamw * the volume from the DFS. 171*da6c28aaSamw */ 172*da6c28aaSamw static int 173*da6c28aaSamw netdfs_s_remove(void *arg, struct mlrpc_xaction *mxa) 174*da6c28aaSamw { 175*da6c28aaSamw struct netdfs_remove *param = arg; 176*da6c28aaSamw netdfs_unc_t unc; 177*da6c28aaSamw DWORD status = ERROR_SUCCESS; 178*da6c28aaSamw 179*da6c28aaSamw if (param->dfs_path == NULL || param->server == NULL || 180*da6c28aaSamw param->share == NULL) { 181*da6c28aaSamw bzero(param, sizeof (struct netdfs_remove)); 182*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 183*da6c28aaSamw return (MLRPC_DRC_OK); 184*da6c28aaSamw } 185*da6c28aaSamw 186*da6c28aaSamw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 187*da6c28aaSamw status = ERROR_INVALID_PARAMETER; 188*da6c28aaSamw } else { 189*da6c28aaSamw if (unc.path == NULL) 190*da6c28aaSamw status = ERROR_BAD_PATHNAME; 191*da6c28aaSamw 192*da6c28aaSamw if (unc.share == NULL) 193*da6c28aaSamw status = ERROR_INVALID_SHARENAME; 194*da6c28aaSamw } 195*da6c28aaSamw 196*da6c28aaSamw if (param->status != ERROR_SUCCESS) { 197*da6c28aaSamw bzero(param, sizeof (struct netdfs_remove)); 198*da6c28aaSamw param->status = status; 199*da6c28aaSamw return (MLRPC_DRC_OK); 200*da6c28aaSamw } 201*da6c28aaSamw 202*da6c28aaSamw bzero(param, sizeof (struct netdfs_remove)); 203*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 204*da6c28aaSamw return (MLRPC_DRC_OK); 205*da6c28aaSamw } 206*da6c28aaSamw 207*da6c28aaSamw /* 208*da6c28aaSamw * Set information about the volume or storage. If the server and share 209*da6c28aaSamw * are specified, the information set is specific to that server and 210*da6c28aaSamw * share. Otherwise the information is specific to the volume as a whole. 211*da6c28aaSamw * 212*da6c28aaSamw * Valid levels are 100-102. 213*da6c28aaSamw */ 214*da6c28aaSamw /*ARGSUSED*/ 215*da6c28aaSamw static int 216*da6c28aaSamw netdfs_s_setinfo(void *arg, struct mlrpc_xaction *mxa) 217*da6c28aaSamw { 218*da6c28aaSamw struct netdfs_setinfo *param = arg; 219*da6c28aaSamw netdfs_unc_t unc; 220*da6c28aaSamw DWORD status = ERROR_SUCCESS; 221*da6c28aaSamw 222*da6c28aaSamw if (param->dfs_path == NULL) { 223*da6c28aaSamw bzero(param, sizeof (struct netdfs_setinfo)); 224*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 225*da6c28aaSamw return (MLRPC_DRC_OK); 226*da6c28aaSamw } 227*da6c28aaSamw 228*da6c28aaSamw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 229*da6c28aaSamw status = ERROR_INVALID_PARAMETER; 230*da6c28aaSamw } else { 231*da6c28aaSamw if (unc.share == NULL) 232*da6c28aaSamw status = ERROR_INVALID_SHARENAME; 233*da6c28aaSamw } 234*da6c28aaSamw 235*da6c28aaSamw if (param->status != ERROR_SUCCESS) { 236*da6c28aaSamw bzero(param, sizeof (struct netdfs_setinfo)); 237*da6c28aaSamw param->status = status; 238*da6c28aaSamw return (MLRPC_DRC_OK); 239*da6c28aaSamw } 240*da6c28aaSamw 241*da6c28aaSamw switch (param->info.level) { 242*da6c28aaSamw case 100: 243*da6c28aaSamw case 101: 244*da6c28aaSamw case 102: 245*da6c28aaSamw break; 246*da6c28aaSamw 247*da6c28aaSamw default: 248*da6c28aaSamw bzero(param, sizeof (struct netdfs_setinfo)); 249*da6c28aaSamw param->status = ERROR_INVALID_LEVEL; 250*da6c28aaSamw return (MLRPC_DRC_OK); 251*da6c28aaSamw } 252*da6c28aaSamw 253*da6c28aaSamw bzero(param, sizeof (struct netdfs_setinfo)); 254*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 255*da6c28aaSamw return (MLRPC_DRC_OK); 256*da6c28aaSamw } 257*da6c28aaSamw 258*da6c28aaSamw /* 259*da6c28aaSamw * Get information about the volume or storage. If the server and share 260*da6c28aaSamw * are specified, the information returned is specific to that server 261*da6c28aaSamw * and share. Otherwise the information is specific to the volume as a 262*da6c28aaSamw * whole. 263*da6c28aaSamw * 264*da6c28aaSamw * Valid levels are 1-4, 100-104. 265*da6c28aaSamw */ 266*da6c28aaSamw /*ARGSUSED*/ 267*da6c28aaSamw static int 268*da6c28aaSamw netdfs_s_getinfo(void *arg, struct mlrpc_xaction *mxa) 269*da6c28aaSamw { 270*da6c28aaSamw struct netdfs_getinfo *param = arg; 271*da6c28aaSamw netdfs_unc_t unc; 272*da6c28aaSamw DWORD status = ERROR_SUCCESS; 273*da6c28aaSamw 274*da6c28aaSamw if (param->dfs_path == NULL) { 275*da6c28aaSamw bzero(param, sizeof (struct netdfs_getinfo)); 276*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 277*da6c28aaSamw return (MLRPC_DRC_OK); 278*da6c28aaSamw } 279*da6c28aaSamw 280*da6c28aaSamw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 281*da6c28aaSamw status = ERROR_INVALID_PARAMETER; 282*da6c28aaSamw } else { 283*da6c28aaSamw if (unc.share == NULL) 284*da6c28aaSamw status = ERROR_INVALID_SHARENAME; 285*da6c28aaSamw } 286*da6c28aaSamw 287*da6c28aaSamw if (param->status != ERROR_SUCCESS) { 288*da6c28aaSamw bzero(param, sizeof (struct netdfs_getinfo)); 289*da6c28aaSamw param->status = status; 290*da6c28aaSamw return (MLRPC_DRC_OK); 291*da6c28aaSamw } 292*da6c28aaSamw 293*da6c28aaSamw switch (param->level) { 294*da6c28aaSamw case 1: 295*da6c28aaSamw case 2: 296*da6c28aaSamw case 3: 297*da6c28aaSamw case 4: 298*da6c28aaSamw case 100: 299*da6c28aaSamw case 101: 300*da6c28aaSamw case 102: 301*da6c28aaSamw case 103: 302*da6c28aaSamw case 104: 303*da6c28aaSamw break; 304*da6c28aaSamw 305*da6c28aaSamw default: 306*da6c28aaSamw bzero(param, sizeof (struct netdfs_getinfo)); 307*da6c28aaSamw param->status = ERROR_INVALID_LEVEL; 308*da6c28aaSamw return (MLRPC_DRC_OK); 309*da6c28aaSamw } 310*da6c28aaSamw 311*da6c28aaSamw bzero(param, sizeof (struct netdfs_getinfo)); 312*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 313*da6c28aaSamw return (MLRPC_DRC_OK); 314*da6c28aaSamw } 315*da6c28aaSamw 316*da6c28aaSamw /* 317*da6c28aaSamw * Get information about all of the volumes in the DFS. dfs_name is 318*da6c28aaSamw * the "server" part of the UNC name used to refer to this particular 319*da6c28aaSamw * DFS. 320*da6c28aaSamw * 321*da6c28aaSamw * Valid levels are 1-3. 322*da6c28aaSamw */ 323*da6c28aaSamw /*ARGSUSED*/ 324*da6c28aaSamw static int 325*da6c28aaSamw netdfs_s_enum(void *arg, struct mlrpc_xaction *mxa) 326*da6c28aaSamw { 327*da6c28aaSamw struct netdfs_enum *param = arg; 328*da6c28aaSamw 329*da6c28aaSamw switch (param->level) { 330*da6c28aaSamw case 1: 331*da6c28aaSamw case 2: 332*da6c28aaSamw case 3: 333*da6c28aaSamw break; 334*da6c28aaSamw 335*da6c28aaSamw default: 336*da6c28aaSamw (void) bzero(param, sizeof (struct netdfs_enum)); 337*da6c28aaSamw param->status = ERROR_INVALID_LEVEL; 338*da6c28aaSamw return (MLRPC_DRC_OK); 339*da6c28aaSamw } 340*da6c28aaSamw 341*da6c28aaSamw (void) bzero(param, sizeof (struct netdfs_enum)); 342*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 343*da6c28aaSamw return (MLRPC_DRC_OK); 344*da6c28aaSamw } 345*da6c28aaSamw 346*da6c28aaSamw /* 347*da6c28aaSamw * Move a DFS volume and all subordinate volumes from one place in the 348*da6c28aaSamw * DFS to another place in the DFS. 349*da6c28aaSamw */ 350*da6c28aaSamw /*ARGSUSED*/ 351*da6c28aaSamw static int 352*da6c28aaSamw netdfs_s_move(void *arg, struct mlrpc_xaction *mxa) 353*da6c28aaSamw { 354*da6c28aaSamw struct netdfs_move *param = arg; 355*da6c28aaSamw 356*da6c28aaSamw if (param->dfs_path == NULL || param->new_path == NULL) { 357*da6c28aaSamw bzero(param, sizeof (struct netdfs_move)); 358*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 359*da6c28aaSamw return (MLRPC_DRC_OK); 360*da6c28aaSamw } 361*da6c28aaSamw 362*da6c28aaSamw bzero(param, sizeof (struct netdfs_move)); 363*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 364*da6c28aaSamw return (MLRPC_DRC_OK); 365*da6c28aaSamw } 366*da6c28aaSamw 367*da6c28aaSamw /* 368*da6c28aaSamw * Rename the current path in a DFS to a new path in the same DFS. 369*da6c28aaSamw */ 370*da6c28aaSamw /*ARGSUSED*/ 371*da6c28aaSamw static int 372*da6c28aaSamw netdfs_s_rename(void *arg, struct mlrpc_xaction *mxa) 373*da6c28aaSamw { 374*da6c28aaSamw struct netdfs_rename *param = arg; 375*da6c28aaSamw 376*da6c28aaSamw if (param->dfs_path == NULL || param->new_path == NULL) { 377*da6c28aaSamw bzero(param, sizeof (struct netdfs_rename)); 378*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 379*da6c28aaSamw return (MLRPC_DRC_OK); 380*da6c28aaSamw } 381*da6c28aaSamw 382*da6c28aaSamw bzero(param, sizeof (struct netdfs_rename)); 383*da6c28aaSamw param->status = ERROR_ACCESS_DENIED; 384*da6c28aaSamw return (MLRPC_DRC_OK); 385*da6c28aaSamw } 386*da6c28aaSamw 387*da6c28aaSamw /* 388*da6c28aaSamw * Add a DFS root share. 389*da6c28aaSamw */ 390*da6c28aaSamw /*ARGSUSED*/ 391*da6c28aaSamw static int 392*da6c28aaSamw netdfs_s_addstdroot(void *arg, struct mlrpc_xaction *mxa) 393*da6c28aaSamw { 394*da6c28aaSamw struct netdfs_addstdroot *param = arg; 395*da6c28aaSamw 396*da6c28aaSamw bzero(param, sizeof (struct netdfs_addstdroot)); 397*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 398*da6c28aaSamw return (MLRPC_DRC_OK); 399*da6c28aaSamw } 400*da6c28aaSamw 401*da6c28aaSamw /* 402*da6c28aaSamw * Remove a DFS root share. 403*da6c28aaSamw */ 404*da6c28aaSamw /*ARGSUSED*/ 405*da6c28aaSamw static int 406*da6c28aaSamw netdfs_s_remstdroot(void *arg, struct mlrpc_xaction *mxa) 407*da6c28aaSamw { 408*da6c28aaSamw struct netdfs_remstdroot *param = arg; 409*da6c28aaSamw 410*da6c28aaSamw bzero(param, sizeof (struct netdfs_remstdroot)); 411*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 412*da6c28aaSamw return (MLRPC_DRC_OK); 413*da6c28aaSamw } 414*da6c28aaSamw 415*da6c28aaSamw /* 416*da6c28aaSamw * Get information about all of the volumes in the DFS. dfs_path is 417*da6c28aaSamw * the "server" part of the UNC name used to refer to this particular 418*da6c28aaSamw * DFS. 419*da6c28aaSamw * 420*da6c28aaSamw * Valid levels are 1-3, 300. 421*da6c28aaSamw */ 422*da6c28aaSamw static int 423*da6c28aaSamw netdfs_s_enumex(void *arg, struct mlrpc_xaction *mxa) 424*da6c28aaSamw { 425*da6c28aaSamw struct netdfs_enumex *param = arg; 426*da6c28aaSamw netdfs_unc_t unc; 427*da6c28aaSamw DWORD status = ERROR_SUCCESS; 428*da6c28aaSamw 429*da6c28aaSamw if (param->dfs_path == NULL) { 430*da6c28aaSamw bzero(param, sizeof (struct netdfs_enumex)); 431*da6c28aaSamw param->status = ERROR_INVALID_PARAMETER; 432*da6c28aaSamw return (MLRPC_DRC_OK); 433*da6c28aaSamw } 434*da6c28aaSamw 435*da6c28aaSamw if (param->resume_handle == NULL) 436*da6c28aaSamw param->resume_handle = MLRPC_HEAP_NEW(mxa, DWORD); 437*da6c28aaSamw 438*da6c28aaSamw if (param->resume_handle) 439*da6c28aaSamw *(param->resume_handle) = 0; 440*da6c28aaSamw 441*da6c28aaSamw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 442*da6c28aaSamw status = ERROR_INVALID_PARAMETER; 443*da6c28aaSamw } else { 444*da6c28aaSamw if (unc.path == NULL) 445*da6c28aaSamw status = ERROR_BAD_PATHNAME; 446*da6c28aaSamw 447*da6c28aaSamw if (unc.share == NULL) 448*da6c28aaSamw status = ERROR_INVALID_SHARENAME; 449*da6c28aaSamw } 450*da6c28aaSamw 451*da6c28aaSamw if (param->status != ERROR_SUCCESS) { 452*da6c28aaSamw bzero(param, sizeof (struct netdfs_enumex)); 453*da6c28aaSamw param->status = status; 454*da6c28aaSamw return (MLRPC_DRC_OK); 455*da6c28aaSamw } 456*da6c28aaSamw 457*da6c28aaSamw param->info = MLRPC_HEAP_NEW(mxa, struct netdfs_enum_info); 458*da6c28aaSamw if (param->info == NULL) { 459*da6c28aaSamw bzero(param, sizeof (struct netdfs_enumex)); 460*da6c28aaSamw param->status = ERROR_NOT_ENOUGH_MEMORY; 461*da6c28aaSamw return (MLRPC_DRC_OK); 462*da6c28aaSamw } 463*da6c28aaSamw 464*da6c28aaSamw bzero(param->info, sizeof (struct netdfs_enumex)); 465*da6c28aaSamw param->status = ERROR_SUCCESS; 466*da6c28aaSamw return (MLRPC_DRC_OK); 467*da6c28aaSamw } 468*da6c28aaSamw 469*da6c28aaSamw /* 470*da6c28aaSamw * Parse a UNC path (\\server\share\path) into components. 471*da6c28aaSamw * Path separators are converted to forward slashes. 472*da6c28aaSamw * 473*da6c28aaSamw * Returns 0 on success, otherwise -1 to indicate an error. 474*da6c28aaSamw */ 475*da6c28aaSamw static int 476*da6c28aaSamw netdfs_unc_parse(struct mlrpc_xaction *mxa, const char *path, netdfs_unc_t *unc) 477*da6c28aaSamw { 478*da6c28aaSamw char *p; 479*da6c28aaSamw 480*da6c28aaSamw if (path == NULL || unc == NULL) 481*da6c28aaSamw return (-1); 482*da6c28aaSamw 483*da6c28aaSamw if ((unc->buf = MLRPC_HEAP_STRSAVE(mxa, (char *)path)) == NULL) 484*da6c28aaSamw return (-1); 485*da6c28aaSamw 486*da6c28aaSamw if ((p = strchr(unc->buf, '\n')) != NULL) 487*da6c28aaSamw *p = '\0'; 488*da6c28aaSamw 489*da6c28aaSamw (void) strsubst(unc->buf, '\\', '/'); 490*da6c28aaSamw (void) strcanon(unc->buf, "/"); 491*da6c28aaSamw 492*da6c28aaSamw unc->server = unc->buf; 493*da6c28aaSamw unc->server += strspn(unc->buf, "/"); 494*da6c28aaSamw 495*da6c28aaSamw if (unc->server) { 496*da6c28aaSamw unc->share = strchr(unc->server, '/'); 497*da6c28aaSamw if ((p = unc->share) != NULL) { 498*da6c28aaSamw unc->share += strspn(unc->share, "/"); 499*da6c28aaSamw *p = '\0'; 500*da6c28aaSamw } 501*da6c28aaSamw } 502*da6c28aaSamw 503*da6c28aaSamw if (unc->share) { 504*da6c28aaSamw unc->path = strchr(unc->share, '/'); 505*da6c28aaSamw if ((p = unc->path) != NULL) { 506*da6c28aaSamw unc->path += strspn(unc->path, "/"); 507*da6c28aaSamw *p = '\0'; 508*da6c28aaSamw } 509*da6c28aaSamw } 510*da6c28aaSamw 511*da6c28aaSamw if (unc->path) { 512*da6c28aaSamw if ((p = strchr(unc->path, '\0')) != NULL) { 513*da6c28aaSamw if (*(--p) == '/') 514*da6c28aaSamw *p = '\0'; 515*da6c28aaSamw } 516*da6c28aaSamw } 517*da6c28aaSamw 518*da6c28aaSamw return (0); 519*da6c28aaSamw } 520