2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Copyright (c) 2008 Secure Endpoints, Inc.
12 * Copyright (c) 2009-2011 Your File System, Inc.
13 * All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are met:
18 * - Redistributions of source code must retain the above copyright notice,
19 * this list of conditions and the following disclaimer.
20 * - Redistributions in binary form must reproduce the above copyright notice,
21 * this list of conditions and the following disclaimer in the documentation
22 * and/or other materials provided with the distribution.
23 * - Neither the name of Secure Endpoints Inc. nor the names of its contributors
24 * may be used to endorse or promote products derived from this software without
25 * specific prior written permission from Secure Endpoints, Inc. and
26 * Your File System, Inc.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <afsconfig.h>
42 #include <afs/param.h>
61 #include "afs/afsrpc.h"
64 #include "smb_iocons.h"
65 #define RDR_IOCTL_PRIVATE 1
70 static RDR_ioctlProc_t *RDR_ioctlProcsp[CM_IOCTL_MAXPROCS];
72 static RDR_ioctl_t * RDR_allIoctls = NULL, *RDR_allIoctlsLast = NULL;
73 static osi_rwlock_t RDR_globalIoctlLock;
75 extern wchar_t RDR_UNCName[];
82 lock_InitializeRWLock(&RDR_globalIoctlLock, "RDR global ioctl lock", LOCK_HIERARCHY_RDR_GLOBAL);
84 for (i=0; i<CM_IOCTL_MAXPROCS; i++)
85 RDR_ioctlProcsp[i] = NULL;
87 RDR_ioctlProcsp[VIOCGETAL] = RDR_IoctlGetACL;
88 RDR_ioctlProcsp[VIOC_FILE_CELL_NAME] = RDR_IoctlGetFileCellName;
89 RDR_ioctlProcsp[VIOCSETAL] = RDR_IoctlSetACL;
90 RDR_ioctlProcsp[VIOC_FLUSHVOLUME] = RDR_IoctlFlushVolume;
91 RDR_ioctlProcsp[VIOCFLUSH] = RDR_IoctlFlushFile;
92 RDR_ioctlProcsp[VIOCSETVOLSTAT] = RDR_IoctlSetVolumeStatus;
93 RDR_ioctlProcsp[VIOCGETVOLSTAT] = RDR_IoctlGetVolumeStatus;
94 RDR_ioctlProcsp[VIOCWHEREIS] = RDR_IoctlWhereIs;
95 RDR_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = RDR_IoctlStatMountPoint;
96 RDR_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = RDR_IoctlDeleteMountPoint;
97 RDR_ioctlProcsp[VIOCCKSERV] = RDR_IoctlCheckServers;
98 RDR_ioctlProcsp[VIOC_GAG] = RDR_IoctlGag;
99 RDR_ioctlProcsp[VIOCCKBACK] = RDR_IoctlCheckVolumes;
100 RDR_ioctlProcsp[VIOCSETCACHESIZE] = RDR_IoctlSetCacheSize;
101 RDR_ioctlProcsp[VIOCGETCACHEPARMS] = RDR_IoctlGetCacheParms;
102 RDR_ioctlProcsp[VIOCGETCELL] = RDR_IoctlGetCell;
103 RDR_ioctlProcsp[VIOCNEWCELL] = RDR_IoctlNewCell;
104 RDR_ioctlProcsp[VIOC_GET_WS_CELL] = RDR_IoctlGetWsCell;
105 RDR_ioctlProcsp[VIOC_AFS_SYSNAME] = RDR_IoctlSysName;
106 RDR_ioctlProcsp[VIOC_GETCELLSTATUS] = RDR_IoctlGetCellStatus;
107 RDR_ioctlProcsp[VIOC_SETCELLSTATUS] = RDR_IoctlSetCellStatus;
108 RDR_ioctlProcsp[VIOC_SETSPREFS] = RDR_IoctlSetSPrefs;
109 RDR_ioctlProcsp[VIOC_GETSPREFS] = RDR_IoctlGetSPrefs;
110 RDR_ioctlProcsp[VIOC_STOREBEHIND] = RDR_IoctlStoreBehind;
111 RDR_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = RDR_IoctlCreateMountPoint;
112 RDR_ioctlProcsp[VIOC_TRACECTL] = RDR_IoctlTraceControl;
113 RDR_ioctlProcsp[VIOCSETTOK] = RDR_IoctlSetToken;
114 RDR_ioctlProcsp[VIOCGETTOK] = RDR_IoctlGetTokenIter;
115 RDR_ioctlProcsp[VIOCNEWGETTOK] = RDR_IoctlGetToken;
116 RDR_ioctlProcsp[VIOCDELTOK] = RDR_IoctlDelToken;
117 RDR_ioctlProcsp[VIOCDELALLTOK] = RDR_IoctlDelAllToken;
118 RDR_ioctlProcsp[VIOC_SYMLINK] = RDR_IoctlSymlink;
119 RDR_ioctlProcsp[VIOC_LISTSYMLINK] = RDR_IoctlListlink;
120 RDR_ioctlProcsp[VIOC_DELSYMLINK] = RDR_IoctlDeletelink;
121 RDR_ioctlProcsp[VIOC_MAKESUBMOUNT] = RDR_IoctlMakeSubmount;
122 RDR_ioctlProcsp[VIOC_GETRXKCRYPT] = RDR_IoctlGetRxkcrypt;
123 RDR_ioctlProcsp[VIOC_SETRXKCRYPT] = RDR_IoctlSetRxkcrypt;
124 RDR_ioctlProcsp[VIOC_ISSYMLINK] = RDR_IoctlIslink;
125 RDR_ioctlProcsp[VIOC_TRACEMEMDUMP] = RDR_IoctlMemoryDump;
126 RDR_ioctlProcsp[VIOC_ISSYMLINK] = RDR_IoctlIslink;
127 RDR_ioctlProcsp[VIOC_FLUSHALL] = RDR_IoctlFlushAllVolumes;
128 RDR_ioctlProcsp[VIOCGETFID] = RDR_IoctlGetFid;
129 RDR_ioctlProcsp[VIOCGETOWNER] = RDR_IoctlGetOwner;
130 RDR_ioctlProcsp[VIOC_RXSTAT_PROC] = RDR_IoctlRxStatProcess;
131 RDR_ioctlProcsp[VIOC_RXSTAT_PEER] = RDR_IoctlRxStatPeer;
132 RDR_ioctlProcsp[VIOC_UUIDCTL] = RDR_IoctlUUIDControl;
133 RDR_ioctlProcsp[VIOC_PATH_AVAILABILITY] = RDR_IoctlPathAvailability;
134 RDR_ioctlProcsp[VIOC_GETFILETYPE] = RDR_IoctlGetFileType;
135 RDR_ioctlProcsp[VIOC_VOLSTAT_TEST] = RDR_IoctlVolStatTest;
136 RDR_ioctlProcsp[VIOC_UNICODECTL] = RDR_IoctlUnicodeControl;
137 RDR_ioctlProcsp[VIOC_SETOWNER] = RDR_IoctlSetOwner;
138 RDR_ioctlProcsp[VIOC_SETGROUP] = RDR_IoctlSetGroup;
139 RDR_ioctlProcsp[VIOCNEWCELL2] = RDR_IoctlNewCell2;
140 RDR_ioctlProcsp[VIOC_GETUNIXMODE] = RDR_IoctlGetUnixMode;
141 RDR_ioctlProcsp[VIOC_SETUNIXMODE] = RDR_IoctlSetUnixMode;
144 /* called to make a fid structure into an IOCTL fid structure */
146 RDR_SetupIoctl(ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid, cm_user_t *userp)
153 lock_ObtainWrite(&RDR_globalIoctlLock);
154 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
155 if (iop->index == index)
160 /* we are reusing a previous ioctl */
161 if (cm_FidCmp(&iop->parentFid, parentFid)) {
162 iop->parentFid = *parentFid;
163 if (iop->parentScp) {
164 cm_ReleaseSCache(iop->parentScp);
165 iop->parentScp = NULL;
167 cm_GetSCache(parentFid, &iop->parentScp, userp, &req);
168 iop->rootFid = *rootFid;
171 /* need to allocate a new one */
172 iop = malloc(sizeof(*iop));
173 memset(iop, 0, sizeof(*iop));
174 if (RDR_allIoctls == NULL)
175 RDR_allIoctls = RDR_allIoctlsLast = iop;
177 iop->prev = RDR_allIoctlsLast;
178 RDR_allIoctlsLast->next = iop;
179 RDR_allIoctlsLast = iop;
182 if (parentFid->cell == 0) {
183 iop->parentFid = cm_data.rootFid;
184 iop->parentScp = cm_RootSCachep(userp, &req);
185 cm_HoldSCache(iop->parentScp);
187 iop->parentFid = *parentFid;
188 cm_GetSCache(parentFid, &iop->parentScp, userp, &req);
190 if (rootFid->cell == 0) {
191 iop->rootFid = cm_data.rootFid;
193 iop->rootFid = *rootFid;
196 lock_ReleaseWrite(&RDR_globalIoctlLock);
201 RDR_CleanupIoctl(ULONG index)
205 lock_ObtainWrite(&RDR_globalIoctlLock);
206 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
207 if (iop->index == index)
213 cm_ReleaseSCache(iop->parentScp);
215 if (iop->ioctl.inAllocp)
216 free(iop->ioctl.inAllocp);
217 if (iop->ioctl.outAllocp)
218 free(iop->ioctl.outAllocp);
220 if (RDR_allIoctls == RDR_allIoctlsLast)
221 RDR_allIoctls = RDR_allIoctlsLast = NULL;
223 if (iop->prev == NULL)
224 RDR_allIoctls = iop->next;
226 iop->prev->next = iop->next;
227 if (iop->next == NULL) {
228 RDR_allIoctlsLast = iop->prev;
229 iop->prev->next = NULL;
231 iop->next->prev = iop->prev;
235 lock_ReleaseWrite(&RDR_globalIoctlLock);
239 /* called when we receive a write call. If this is the first write call after
240 * a series of reads (or the very first call), then we start a new call.
241 * We also ensure that things are properly initialized for the start of a call.
244 RDR_IoctlPrepareWrite(RDR_ioctl_t *ioctlp)
246 /* make sure the buffer(s) are allocated */
247 if (!ioctlp->ioctl.inAllocp)
248 ioctlp->ioctl.inAllocp = malloc(CM_IOCTL_MAXDATA);
249 if (!ioctlp->ioctl.outAllocp)
250 ioctlp->ioctl.outAllocp = malloc(CM_IOCTL_MAXDATA);
252 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
253 (void) memset(ioctlp->ioctl.inAllocp, 0, CM_IOCTL_MAXDATA);
254 (void) memset(ioctlp->ioctl.outAllocp, 0, CM_IOCTL_MAXDATA);
256 /* and make sure that we've reset our state for the new incoming request */
257 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
258 ioctlp->ioctl.inCopied = 0;
259 ioctlp->ioctl.outCopied = 0;
260 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
261 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
262 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
266 /* called when we receive a read call, does the send of the received data if
267 * this is the first read call. This is the function that actually makes the
268 * call to the ioctl code.
271 RDR_IoctlPrepareRead(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
274 RDR_ioctlProc_t *procp = NULL;
277 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
278 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
280 /* do the call now, or fail if we didn't get an opcode, or
281 * enough of an opcode.
283 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
284 return CM_ERROR_INVAL;
286 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
287 ioctlp->ioctl.inDatap += sizeof(afs_int32);
289 osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode);
291 /* check for opcode out of bounds */
292 if (opcode < 0 || opcode >= CM_IOCTL_MAXPROCS)
293 return CM_ERROR_TOOBIG;
295 /* check for no such proc */
296 procp = RDR_ioctlProcsp[opcode];
298 return CM_ERROR_BADOP;
300 /* otherwise, make the call */
301 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
302 code = (*procp)(ioctlp, userp, pflags);
304 osi_Log1(afsd_logp, "Ioctl return code 0x%x", code);
306 /* copy in return code */
307 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
313 RDR_FindIoctl(ULONG index)
317 lock_ObtainRead(&RDR_globalIoctlLock);
318 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
319 if (iop->index == index)
322 lock_ReleaseRead(&RDR_globalIoctlLock);
326 /* called from RDR_ReceiveCoreRead when we receive a read on the ioctl fid */
328 RDR_IoctlRead(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer, ULONG *pBytesProcessed, cm_req_t *reqp, afs_uint32 pflags)
334 iop = RDR_FindIoctl(RequestId);
336 return CM_ERROR_BADFD;
338 /* turn the connection around, if required */
339 code = RDR_IoctlPrepareRead(iop, userp, pflags);
343 count = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
344 if (BufferLength < count)
345 count = BufferLength;
347 /* now copy the data into the response packet */
348 memcpy((char *)MappedBuffer, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
350 /* and adjust the counters */
351 iop->ioctl.outCopied += count;
353 *pBytesProcessed = count;
358 /* called from RDR_PioctWRite when we receive a write call on the IOCTL
362 RDR_IoctlWrite(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer, cm_req_t *reqp)
366 iop = RDR_FindIoctl(RequestId);
368 return CM_ERROR_BADFD;
370 RDR_IoctlPrepareWrite(iop);
372 if (BufferLength + iop->ioctl.inCopied > CM_IOCTL_MAXDATA)
373 return CM_ERROR_TOOBIG;
376 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, (char *)MappedBuffer, BufferLength);
379 iop->ioctl.inCopied += BufferLength;
385 /* parse the passed-in file name and do a namei on it. If we fail,
386 * return an error code, otherwise return the vnode located in *scpp.
388 #define CM_PARSE_FLAG_LITERAL 1
391 RDR_ParseIoctlPath(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
392 cm_scache_t **scpp, afs_uint32 flags)
395 cm_scache_t *substRootp = NULL;
396 cm_scache_t *iscp = NULL;
398 wchar_t *relativePath = NULL;
399 wchar_t *lastComponent = NULL;
400 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
401 int free_path = FALSE;
403 inPath = ioctlp->ioctl.inDatap;
404 /* setup the next data value for the caller to use */
405 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;;
407 osi_Log1(afsd_logp, "RDR_ParseIoctlPath inPath %s", osi_LogSaveString(afsd_logp,inPath));
409 /* This is usually the file name, but for StatMountPoint it is the path. */
410 /* ioctlp->inDatap can be either of the form:
413 * \\netbios-name\submount\path\.
414 * \\netbios-name\submount\path\file
417 /* We do not perform path name translation on the ioctl path data
418 * because these paths were not translated by Windows through the
419 * file system API. Therefore, they are not OEM characters but
420 * whatever the display character set is.
423 // TranslateExtendedChars(relativePath);
425 /* This is usually nothing, but for StatMountPoint it is the file name. */
426 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
428 /* If the string starts with our UTF-8 prefix (which is the
429 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
430 strings), we assume that the provided path is UTF-8. Otherwise
431 we have to convert the string to UTF-8, since that is what we
432 want to use everywhere else.*/
434 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
435 /* String is UTF-8 */
436 inPath += utf8_prefix_size;
437 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
439 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
440 osi_Log1(afsd_logp, "RDR_ParseIoctlPath UTF8 relativePath %S",
441 osi_LogSaveStringW(afsd_logp,relativePath));
444 /* Not a UTF-8 string */
445 /* TODO: If this is an OEM string, we should convert it to UTF-8. */
446 if (smb_StoreAnsiFilenames) {
447 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
451 relativePath = malloc(cch * sizeof(clientchar_t));
452 cm_AnsiToClientString(inPath, -1, relativePath, cch);
454 TranslateExtendedChars(inPath);
456 cch = cm_OemToClientString(inPath, -1, NULL, 0);
460 relativePath = malloc(cch * sizeof(clientchar_t));
461 cm_OemToClientString(inPath, -1, relativePath, cch);
463 osi_Log1(afsd_logp, "RDR_ParseIoctlPath ASCII relativePath %S",
464 osi_LogSaveStringW(afsd_logp,relativePath));
467 if (relativePath[0] == relativePath[1] &&
468 relativePath[1] == '\\' &&
469 !cm_ClientStrCmpNI(RDR_UNCName,relativePath+2,(int)wcslen(RDR_UNCName)))
471 wchar_t shareName[256];
476 /* We may have found a UNC path.
477 * If the first component is the RDR UNC Name,
478 * then throw out the second component (the submount)
479 * since it had better expand into the value of ioctl->tidPathp
481 p = relativePath + 2 + wcslen(RDR_UNCName) + 1; /* buffer overflow vuln.? */
482 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
485 for (i = 0; *p && *p != '\\'; i++,p++ ) {
488 p++; /* skip past trailing slash */
489 shareName[i] = 0; /* terminate string */
491 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
493 /* we found a sharename, therefore use the resulting path */
494 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
495 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
496 userp, NULL, reqp, &substRootp);
499 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [1] code 0x%x", code);
505 lastComponent = cm_ClientStrRChr(p, '\\');
506 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
507 *lastComponent = '\0';
510 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
511 userp, NULL, reqp, &iscp);
513 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
514 userp, NULL, reqp, scpp);
516 cm_ReleaseSCache(iscp);
518 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
519 userp, NULL, reqp, scpp);
521 cm_ReleaseSCache(substRootp);
523 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [2] code 0x%x", code);
529 /* otherwise, treat the name as a cellname mounted off the afs root.
530 * This requires that we reconstruct the shareName string with
531 * leading and trailing slashes.
533 p = relativePath + 2 + wcslen(RDR_UNCName) + 1;
534 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
538 for (i = 1; *p && *p != '\\'; i++,p++ ) {
541 p++; /* skip past trailing slash */
542 shareName[i++] = '/'; /* add trailing slash */
543 shareName[i] = 0; /* terminate string */
546 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
547 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
548 userp, NULL, reqp, &substRootp);
550 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [3] code 0x%x", code);
556 lastComponent = cm_ClientStrRChr(p, '\\');
557 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
558 *lastComponent = '\0';
561 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
562 userp, NULL, reqp, &iscp);
564 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
565 userp, NULL, reqp, scpp);
567 cm_ReleaseSCache(iscp);
569 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
570 userp, NULL, reqp, scpp);
574 cm_ReleaseSCache(substRootp);
575 osi_Log1(afsd_logp,"RDR_ParseIoctlPath code [4] 0x%x", code);
582 code = cm_GetSCache(&ioctlp->parentFid, &substRootp, userp, reqp);
584 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [6] code 0x%x", code);
590 lastComponent = cm_ClientStrRChr(relativePath, '\\');
591 if (lastComponent && (lastComponent - relativePath) > 1 && wcslen(lastComponent) > 1) {
592 *lastComponent = '\0';
595 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
596 userp, NULL, reqp, &iscp);
598 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
599 userp, NULL, reqp, scpp);
601 cm_ReleaseSCache(iscp);
603 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
604 userp, NULL, reqp, scpp);
607 cm_ReleaseSCache(substRootp);
608 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [7] code 0x%x", code);
616 cm_ReleaseSCache(substRootp);
621 /* Ensure that the status object is up to date */
622 lock_ObtainWrite(&(*scpp)->rw);
623 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
624 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
626 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
627 lock_ReleaseWrite(&(*scpp)->rw);
629 /* and return success */
630 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [8] code 0x%x", code);
636 #define LEAF_SIZE 256
637 /* parse the passed-in file name and do a namei on its parent. If we fail,
638 * return an error code, otherwise return the vnode located in *scpp.
641 RDR_ParseIoctlParent(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
642 cm_scache_t **scpp, wchar_t *leafp)
645 clientchar_t tbuffer[1024];
646 clientchar_t *tp, *jp;
647 cm_scache_t *substRootp = NULL;
648 clientchar_t *inpathp;
650 int free_path = FALSE;
652 inpathdatap = ioctlp->ioctl.inDatap;
654 /* If the string starts with our UTF-8 prefix (which is the
655 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
656 strings), we assume that the provided path is UTF-8. Otherwise
657 we have to convert the string to UTF-8, since that is what we
658 want to use everywhere else.*/
660 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
661 /* String is UTF-8 */
662 inpathdatap += utf8_prefix_size;
663 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
665 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
666 osi_Log1(afsd_logp, "RDR_ParseIoctlParent UTF8 inpathp %S",
667 osi_LogSaveStringW(afsd_logp, inpathp));
671 /* Not a UTF-8 string */
672 /* TODO: If this is an OEM string, we should convert it to
674 if (smb_StoreAnsiFilenames) {
675 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
679 inpathp = malloc(cch * sizeof(clientchar_t));
680 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
682 TranslateExtendedChars(inpathdatap);
684 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
688 inpathp = malloc(cch * sizeof(clientchar_t));
689 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
691 osi_Log1(afsd_logp, "RDR_ParseIoctlParent ASCII inpathp %S",
692 osi_LogSaveStringW(afsd_logp, inpathp));
695 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
696 tp = cm_ClientStrRChr(tbuffer, '\\');
697 jp = cm_ClientStrRChr(tbuffer, '/');
700 else if (jp && (tp - tbuffer) < (jp - tbuffer))
703 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
705 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
710 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
715 inpathp = NULL; /* We don't need this from this point on */
717 if (tbuffer[0] == tbuffer[1] &&
718 tbuffer[1] == '\\' &&
719 !cm_ClientStrCmpNI(RDR_UNCName,tbuffer+2, (int)wcslen(RDR_UNCName)))
721 wchar_t shareName[256];
725 /* We may have found a UNC path.
726 * If the first component is the UNC Name,
727 * then throw out the second component (the submount)
728 * since it had better expand into the value of ioctl->tidPathp
731 p = tbuffer + 2 + cm_ClientStrLen(RDR_UNCName) + 1;
732 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
735 for (i = 0; *p && *p != '\\'; i++,p++ ) {
738 p++; /* skip past trailing slash */
739 shareName[i] = 0; /* terminate string */
741 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
743 /* we found a sharename, therefore use the resulting path */
744 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
745 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
746 userp, NULL, reqp, &substRootp);
749 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [1] code 0x%x", code);
752 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
753 userp, NULL, reqp, scpp);
754 cm_ReleaseSCache(substRootp);
756 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [2] code 0x%x", code);
760 /* otherwise, treat the name as a cellname mounted off the afs root.
761 * This requires that we reconstruct the shareName string with
762 * leading and trailing slashes.
764 p = tbuffer + 2 + wcslen(RDR_UNCName) + 1;
765 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
769 for (i = 1; *p && *p != '\\'; i++,p++ ) {
772 p++; /* skip past trailing slash */
773 shareName[i++] = '/'; /* add trailing slash */
774 shareName[i] = 0; /* terminate string */
776 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
777 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
778 userp, NULL, reqp, &substRootp);
780 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [3] code 0x%x", code);
783 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
784 userp, NULL, reqp, scpp);
785 cm_ReleaseSCache(substRootp);
787 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [4] code 0x%x", code);
792 code = cm_GetSCache(&ioctlp->rootFid, &substRootp, userp, reqp);
794 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [5] code 0x%x", code);
797 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
798 userp, NULL, reqp, scpp);
799 cm_ReleaseSCache(substRootp);
801 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [6] code 0x%x", code);
806 /* # of bytes of path */
807 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
808 ioctlp->ioctl.inDatap += code;
810 /* Ensure that the status object is up to date */
811 lock_ObtainWrite(&(*scpp)->rw);
812 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
813 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
815 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
816 lock_ReleaseWrite(&(*scpp)->rw);
818 /* and return success */
819 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [7] code 0x%x", code);
824 RDR_IoctlSetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
831 struct ClearToken ct;
837 wchar_t *smbname = NULL;
838 wchar_t *uname = NULL;
840 int release_userp = 0;
842 saveDataPtr = ioctlp->ioctl.inDatap;
844 cm_SkipIoctlPath(&ioctlp->ioctl);
846 tp = ioctlp->ioctl.inDatap;
849 memcpy(&ticketLen, tp, sizeof(ticketLen));
850 tp += sizeof(ticketLen);
851 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN) {
852 code = CM_ERROR_INVAL;
856 /* remember ticket and skip over it for now */
860 /* clear token size */
861 memcpy(&ctSize, tp, sizeof(ctSize));
862 tp += sizeof(ctSize);
863 if (ctSize != sizeof(struct ClearToken)) {
864 code = CM_ERROR_INVAL;
869 memcpy(&ct, tp, ctSize);
871 if (ct.AuthHandle == -1)
872 ct.AuthHandle = 999; /* more rxvab compat stuff */
874 /* more stuff, if any */
875 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
876 /* flags: logon flag */
877 memcpy(&flags, tp, sizeof(int));
881 cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
883 code = CM_ERROR_NOSUCHCELL;
886 tp += strlen(tp) + 1;
889 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
890 tp += strlen(tp) + 1;
892 if (flags & PIOCTL_LOGON) {
893 /* SMB user name with which to associate tokens */
894 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
895 tp += strlen(tp) + 1;
896 osi_Log2(afsd_logp,"RDR_IoctlSetToken for user [%S] smbname [%S]",
897 osi_LogSaveStringW(afsd_logp,uname),
898 osi_LogSaveStringW(afsd_logp,smbname));
900 osi_Log1(afsd_logp,"RDR_IoctlSetToken for user [%S]",
901 osi_LogSaveStringW(afsd_logp, uname));
905 memcpy(&uuid, tp, sizeof(uuid));
906 if (!cm_FindTokenEvent(uuid, sessionKey, NULL)) {
907 code = CM_ERROR_INVAL;
911 #if defined(NO_AUTH_GROUPS)
912 /* after obtaining the session key check whether we can use it */
913 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
914 code = CM_ERROR_NOACCESS;
919 cellp = cm_data.rootCellp;
920 osi_Log0(afsd_logp,"cm_IoctlSetToken - no name specified");
923 #if defined(NO_AUTH_GROUPS)
924 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
925 wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
926 int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
928 DWORD dwSize1, dwSize2;
929 wchar_t *pszRefDomain = NULL;
930 SID_NAME_USE snu = SidTypeGroup;
931 clientchar_t * secSidString = NULL;
934 GetComputerNameW(cname, &cnamelen);
938 * The input name is probably not a SID for the user which is how
939 * the user is now being identified as a result of the SMB
940 * extended authentication. See if we can obtain the SID for the
941 * specified name. If we can, use that instead of the name
945 dwSize1 = dwSize2 = 0;
946 LookupAccountNameW( NULL /* System Name to begin Search */,
951 gle = GetLastError();
952 if (gle == ERROR_INSUFFICIENT_BUFFER) {
953 pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
955 * Although dwSize2 is supposed to include the terminating
956 * NUL character, on Win7 it does not.
958 pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
961 if ( pSid && pszRefDomain ) {
962 if (LookupAccountNameW( NULL /* System Name to begin Search */,
965 pszRefDomain, &dwSize2,
967 ConvertSidToStringSidW(pSid, &secSidString);
971 userp = smb_FindCMUserBySID( secSidString, cname,
972 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
973 LocalFree(secSidString);
980 if (!ConvertStringSidToSidW( smbname, &pSid)) {
981 userp = smb_FindCMUserBySID( smbname, cname,
982 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
984 userp = smb_FindCMUserByName( smbname, cname,
985 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
998 /* store the token */
999 lock_ObtainMutex(&userp->mx);
1000 ucellp = cm_GetUCell(userp, cellp);
1001 osi_Log1(afsd_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1002 ucellp->ticketLen = ticketLen;
1003 if (ucellp->ticketp)
1004 free(ucellp->ticketp); /* Discard old token if any */
1005 ucellp->ticketp = malloc(ticketLen);
1006 memcpy(ucellp->ticketp, ticket, ticketLen);
1008 * Get the session key from the RPC, rather than from the pioctl.
1011 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1013 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1014 ucellp->kvno = ct.AuthHandle;
1015 ucellp->expirationTime = ct.EndTimestamp;
1018 ucellp->uid = ANONYMOUSID;
1021 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1023 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1026 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1027 lock_ReleaseMutex(&userp->mx);
1029 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1030 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1033 cm_ResetACLCache(cellp, userp);
1036 SecureZeroMemory(sessionKey, sizeof(sessionKey));
1039 cm_ReleaseUser(userp);
1051 RDR_IoctlGetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1056 cm_ioctlQueryOptions_t *optionsp;
1057 afs_uint32 flags = 0;
1061 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1062 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1063 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1065 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1067 cm_SkipIoctlPath(&ioctlp->ioctl);
1068 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1069 optionsp->fid.vnode, optionsp->fid.unique);
1070 code = cm_GetSCache(&fid, &scp, userp, &req);
1072 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1077 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1079 cm_ReleaseSCache(scp);
1084 RDR_IoctlSetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1090 afs_uint32 flags = 0;
1094 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1098 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1100 cm_ReleaseSCache(scp);
1105 RDR_IoctlGetFileCellName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1110 cm_ioctlQueryOptions_t *optionsp;
1111 afs_uint32 flags = 0;
1115 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1116 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1117 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1119 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1121 cm_SkipIoctlPath(&ioctlp->ioctl);
1122 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1123 optionsp->fid.vnode, optionsp->fid.unique);
1124 code = cm_GetSCache(&fid, &scp, userp, &req);
1126 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1131 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1133 cm_ReleaseSCache(scp);
1139 RDR_IoctlFlushAllVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1145 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1147 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1151 RDR_IoctlFlushVolume(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1156 cm_ioctlQueryOptions_t *optionsp;
1157 afs_uint32 flags = 0;
1161 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1162 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1163 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1165 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1167 cm_SkipIoctlPath(&ioctlp->ioctl);
1168 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1169 optionsp->fid.vnode, optionsp->fid.unique);
1170 code = cm_GetSCache(&fid, &scp, userp, &req);
1172 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1177 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1179 cm_ReleaseSCache(scp);
1185 RDR_IoctlFlushFile(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1190 cm_ioctlQueryOptions_t *optionsp;
1191 afs_uint32 flags = 0;
1195 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1196 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1197 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1199 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1201 cm_SkipIoctlPath(&ioctlp->ioctl);
1202 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1203 optionsp->fid.vnode, optionsp->fid.unique);
1204 code = cm_GetSCache(&fid, &scp, userp, &req);
1206 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1211 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1213 cm_ReleaseSCache(scp);
1218 RDR_IoctlSetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1226 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1227 if (code) return code;
1229 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1230 cm_ReleaseSCache(scp);
1236 RDR_IoctlGetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1240 cm_ioctlQueryOptions_t *optionsp;
1241 afs_uint32 flags = 0;
1246 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1247 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1248 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1250 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1252 cm_SkipIoctlPath(&ioctlp->ioctl);
1253 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1254 optionsp->fid.vnode, optionsp->fid.unique);
1255 code = cm_GetSCache(&fid, &scp, userp, &req);
1257 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1262 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1264 cm_ReleaseSCache(scp);
1270 RDR_IoctlGetFid(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1275 cm_ioctlQueryOptions_t * optionsp;
1276 afs_uint32 flags = 0;
1280 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1281 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1282 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1284 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1288 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1290 cm_ReleaseSCache(scp);
1296 RDR_IoctlGetFileType(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1301 cm_ioctlQueryOptions_t * optionsp;
1302 afs_uint32 flags = 0;
1306 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1307 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1308 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1310 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1312 cm_SkipIoctlPath(&ioctlp->ioctl);
1313 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1314 optionsp->fid.vnode, optionsp->fid.unique);
1315 code = cm_GetSCache(&fid, &scp, userp, &req);
1317 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1322 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1324 cm_ReleaseSCache(scp);
1330 RDR_IoctlGetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1335 cm_ioctlQueryOptions_t *optionsp;
1336 afs_uint32 flags = 0;
1340 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1341 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1342 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1344 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1346 cm_SkipIoctlPath(&ioctlp->ioctl);
1347 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1348 optionsp->fid.vnode, optionsp->fid.unique);
1349 code = cm_GetSCache(&fid, &scp, userp, &req);
1351 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1356 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1358 cm_ReleaseSCache(scp);
1364 RDR_IoctlWhereIs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1369 cm_ioctlQueryOptions_t *optionsp;
1370 afs_uint32 flags = 0;
1374 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1375 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1376 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1378 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1380 cm_SkipIoctlPath(&ioctlp->ioctl);
1381 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1382 optionsp->fid.vnode, optionsp->fid.unique);
1383 code = cm_GetSCache(&fid, &scp, userp, &req);
1385 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1390 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1392 cm_ReleaseSCache(scp);
1399 RDR_IoctlStatMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1407 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1411 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1413 cm_ReleaseSCache(dscp);
1419 RDR_IoctlDeleteMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1427 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1431 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1433 cm_ReleaseSCache(dscp);
1439 RDR_IoctlCheckServers(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1441 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1443 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1447 RDR_IoctlGag(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1449 /* we don't print anything superfluous, so we don't support the gag call */
1450 return CM_ERROR_INVAL;
1454 RDR_IoctlCheckVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1456 cm_SkipIoctlPath(&ioctlp->ioctl);
1458 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1461 afs_int32 RDR_IoctlSetCacheSize(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1463 cm_SkipIoctlPath(&ioctlp->ioctl);
1465 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1470 RDR_IoctlTraceControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1472 cm_SkipIoctlPath(&ioctlp->ioctl);
1474 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1478 RDR_IoctlGetCacheParms(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1480 cm_SkipIoctlPath(&ioctlp->ioctl);
1482 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1486 RDR_IoctlGetCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1488 cm_SkipIoctlPath(&ioctlp->ioctl);
1490 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1494 RDR_IoctlNewCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1496 cm_SkipIoctlPath(&ioctlp->ioctl);
1498 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1502 RDR_IoctlNewCell2(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1504 cm_SkipIoctlPath(&ioctlp->ioctl);
1506 return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1510 RDR_IoctlGetWsCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1512 cm_SkipIoctlPath(&ioctlp->ioctl);
1514 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1518 RDR_IoctlSysName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1520 cm_SkipIoctlPath(&ioctlp->ioctl);
1522 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1526 RDR_IoctlGetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1528 cm_SkipIoctlPath(&ioctlp->ioctl);
1530 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1534 RDR_IoctlSetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1536 cm_SkipIoctlPath(&ioctlp->ioctl);
1538 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1542 RDR_IoctlSetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1544 cm_SkipIoctlPath(&ioctlp->ioctl);
1546 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1550 RDR_IoctlGetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1552 cm_SkipIoctlPath(&ioctlp->ioctl);
1554 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1558 RDR_IoctlStoreBehind(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1560 /* we ignore default asynchrony since we only have one way
1561 * of doing this today.
1567 RDR_IoctlCreateMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1571 wchar_t leaf[LEAF_SIZE];
1576 code = RDR_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1580 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1582 cm_ReleaseSCache(dscp);
1587 RDR_IoctlSymlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1591 wchar_t leaf[LEAF_SIZE];
1596 code = RDR_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1597 if (code) return code;
1599 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1601 cm_ReleaseSCache(dscp);
1607 RDR_IoctlListlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1615 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1616 if (code) return code;
1618 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1620 cm_ReleaseSCache(dscp);
1625 RDR_IoctlIslink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1626 {/*CHECK FOR VALID SYMLINK*/
1633 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1634 if (code) return code;
1636 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1638 cm_ReleaseSCache(dscp);
1644 RDR_IoctlDeletelink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1652 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1653 if (code) return code;
1655 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1657 cm_ReleaseSCache(dscp);
1663 RDR_IoctlGetTokenIter(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1665 cm_SkipIoctlPath(&ioctlp->ioctl);
1667 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1671 RDR_IoctlGetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1673 cm_SkipIoctlPath(&ioctlp->ioctl);
1675 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1680 RDR_IoctlDelToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1682 cm_SkipIoctlPath(&ioctlp->ioctl);
1684 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1689 RDR_IoctlDelAllToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1691 cm_SkipIoctlPath(&ioctlp->ioctl);
1693 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1698 RDR_IoctlMakeSubmount(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1700 cm_SkipIoctlPath(&ioctlp->ioctl);
1702 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1706 RDR_IoctlGetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1708 cm_SkipIoctlPath(&ioctlp->ioctl);
1710 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1714 RDR_IoctlSetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1716 cm_SkipIoctlPath(&ioctlp->ioctl);
1718 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1722 RDR_IoctlRxStatProcess(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1724 cm_SkipIoctlPath(&ioctlp->ioctl);
1726 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1731 RDR_IoctlRxStatPeer(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1733 cm_SkipIoctlPath(&ioctlp->ioctl);
1735 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1739 RDR_IoctlUnicodeControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1741 cm_SkipIoctlPath(&ioctlp->ioctl);
1743 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1747 RDR_IoctlUUIDControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1749 cm_SkipIoctlPath(&ioctlp->ioctl);
1751 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1756 RDR_IoctlMemoryDump(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1758 cm_SkipIoctlPath(&ioctlp->ioctl);
1760 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1764 RDR_IoctlPathAvailability(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1769 cm_ioctlQueryOptions_t *optionsp;
1770 afs_uint32 flags = 0;
1774 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1775 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1776 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1778 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1780 cm_SkipIoctlPath(&ioctlp->ioctl);
1781 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1782 optionsp->fid.vnode, optionsp->fid.unique);
1783 code = cm_GetSCache(&fid, &scp, userp, &req);
1785 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1790 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1791 cm_ReleaseSCache(scp);
1796 RDR_IoctlVolStatTest(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1802 cm_SkipIoctlPath(&ioctlp->ioctl);
1804 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
1810 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1814 RDR_IoctlSetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1819 cm_ioctlQueryOptions_t *optionsp;
1820 afs_uint32 flags = 0;
1824 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1826 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1827 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1829 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1831 cm_SkipIoctlPath(&ioctlp->ioctl);
1832 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1833 optionsp->fid.vnode, optionsp->fid.unique);
1834 code = cm_GetSCache(&fid, &scp, userp, &req);
1836 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1841 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1844 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
1846 cm_ReleaseSCache(scp);
1854 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1858 RDR_IoctlSetGroup(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1863 cm_ioctlQueryOptions_t *optionsp;
1864 afs_uint32 flags = 0;
1868 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1870 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1871 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1873 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1875 cm_SkipIoctlPath(&ioctlp->ioctl);
1876 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1877 optionsp->fid.vnode, optionsp->fid.unique);
1878 code = cm_GetSCache(&fid, &scp, userp, &req);
1880 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1885 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1888 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
1890 cm_ReleaseSCache(scp);
1896 RDR_IoctlGetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1901 cm_ioctlQueryOptions_t *optionsp;
1902 afs_uint32 flags = 0;
1906 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1907 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1908 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1910 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1912 cm_SkipIoctlPath(&ioctlp->ioctl);
1913 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1914 optionsp->fid.vnode, optionsp->fid.unique);
1915 code = cm_GetSCache(&fid, &scp, userp, &req);
1917 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1922 code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
1924 cm_ReleaseSCache(scp);
1932 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1936 RDR_IoctlSetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1941 cm_ioctlQueryOptions_t *optionsp;
1942 afs_uint32 flags = 0;
1946 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1948 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1949 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1951 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1953 cm_SkipIoctlPath(&ioctlp->ioctl);
1954 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1955 optionsp->fid.vnode, optionsp->fid.unique);
1956 code = cm_GetSCache(&fid, &scp, userp, &req);
1958 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1963 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1966 code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
1968 cm_ReleaseSCache(scp);