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;
142 RDR_ioctlProcsp[VIOC_GETVERIFYDATA] = RDR_IoctlGetVerifyData;
143 RDR_ioctlProcsp[VIOC_SETVERIFYDATA] = RDR_IoctlSetVerifyData;
147 RDR_ShutdownIoctl(void)
149 lock_FinalizeRWLock(&RDR_globalIoctlLock);
152 /* called to make a fid structure into an IOCTL fid structure */
154 RDR_SetupIoctl(ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid, cm_user_t *userp, cm_req_t *reqp)
158 lock_ObtainWrite(&RDR_globalIoctlLock);
159 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
160 if (iop->index == index)
168 /* we are reusing a previous ioctl */
169 if (cm_FidCmp(&iop->parentFid, parentFid)) {
170 iop->parentFid = *parentFid;
171 if (iop->parentScp) {
172 cm_ReleaseSCache(iop->parentScp);
173 iop->parentScp = NULL;
175 cm_GetSCache(parentFid, NULL, &iop->parentScp, userp, reqp);
176 iop->rootFid = *rootFid;
179 /* need to allocate a new one */
180 iop = malloc(sizeof(*iop));
181 memset(iop, 0, sizeof(*iop));
182 if (RDR_allIoctls == NULL)
183 RDR_allIoctls = RDR_allIoctlsLast = iop;
185 iop->prev = RDR_allIoctlsLast;
186 RDR_allIoctlsLast->next = iop;
187 RDR_allIoctlsLast = iop;
191 if (parentFid->cell == 0) {
192 iop->parentFid = cm_data.rootFid;
193 iop->parentScp = cm_RootSCachep(userp, reqp);
194 cm_HoldSCache(iop->parentScp);
196 iop->parentFid = *parentFid;
197 cm_GetSCache(parentFid, NULL, &iop->parentScp, userp, reqp);
199 if (rootFid->cell == 0) {
200 iop->rootFid = cm_data.rootFid;
202 iop->rootFid = *rootFid;
205 lock_ReleaseWrite(&RDR_globalIoctlLock);
209 RDR_DestroyIoctl(RDR_ioctl_t *iop)
215 cm_ReleaseSCache(iop->parentScp);
217 if (iop->ioctl.inAllocp)
218 free(iop->ioctl.inAllocp);
219 if (iop->ioctl.outAllocp)
220 free(iop->ioctl.outAllocp);
222 if (RDR_allIoctls == RDR_allIoctlsLast)
223 RDR_allIoctls = RDR_allIoctlsLast = NULL;
225 if (iop->prev == NULL)
226 RDR_allIoctls = iop->next;
228 iop->prev->next = iop->next;
229 if (iop->next == NULL) {
230 RDR_allIoctlsLast = iop->prev;
231 iop->prev->next = NULL;
233 iop->next->prev = iop->prev;
239 RDR_CleanupIoctl(ULONG index)
243 lock_ObtainWrite(&RDR_globalIoctlLock);
244 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
245 if (iop->index == index)
250 if (iop->refCount == 0) {
251 RDR_DestroyIoctl(iop);
255 iop->flags |= RDR_IOCTL_FLAG_CLEANED;
258 lock_ReleaseWrite(&RDR_globalIoctlLock);
261 /* called when we receive a write call. If this is the first write call after
262 * a series of reads (or the very first call), then we start a new call.
263 * We also ensure that things are properly initialized for the start of a call.
266 RDR_IoctlPrepareWrite(RDR_ioctl_t *ioctlp)
268 /* make sure the buffer(s) are allocated */
269 if (!ioctlp->ioctl.inAllocp)
270 ioctlp->ioctl.inAllocp = malloc(CM_IOCTL_MAXDATA);
271 if (!ioctlp->ioctl.outAllocp)
272 ioctlp->ioctl.outAllocp = malloc(CM_IOCTL_MAXDATA);
274 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
275 (void) memset(ioctlp->ioctl.inAllocp, 0, CM_IOCTL_MAXDATA);
276 (void) memset(ioctlp->ioctl.outAllocp, 0, CM_IOCTL_MAXDATA);
278 /* and make sure that we've reset our state for the new incoming request */
279 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
280 ioctlp->ioctl.inCopied = 0;
281 ioctlp->ioctl.outCopied = 0;
282 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
283 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
284 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
288 /* called when we receive a read call, does the send of the received data if
289 * this is the first read call. This is the function that actually makes the
290 * call to the ioctl code.
293 RDR_IoctlPrepareRead(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
296 RDR_ioctlProc_t *procp = NULL;
299 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
300 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
302 /* do the call now, or fail if we didn't get an opcode, or
303 * enough of an opcode.
305 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
306 return CM_ERROR_INVAL;
308 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
309 ioctlp->ioctl.inDatap += sizeof(afs_int32);
311 osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode);
313 /* check for opcode out of bounds */
314 if (opcode < 0 || opcode >= CM_IOCTL_MAXPROCS)
315 return CM_ERROR_TOOBIG;
317 /* check for no such proc */
318 procp = RDR_ioctlProcsp[opcode];
320 return CM_ERROR_BADOP;
322 /* otherwise, make the call */
323 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
324 code = (*procp)(ioctlp, userp, pflags);
326 osi_Log1(afsd_logp, "Ioctl return code 0x%x", code);
328 /* copy in return code */
329 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
335 RDR_FindIoctl(ULONG index)
339 lock_ObtainRead(&RDR_globalIoctlLock);
340 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
341 if (iop->index == index &&
342 !(iop->flags & RDR_IOCTL_FLAG_CLEANED)) {
343 InterlockedIncrement(&iop->refCount);
347 lock_ReleaseRead(&RDR_globalIoctlLock);
352 RDR_ReleaseIoctl(RDR_ioctl_t * iop)
354 lock_ObtainWrite(&RDR_globalIoctlLock);
355 InterlockedDecrement(&iop->refCount);
357 if (iop->refCount == 0 &&
358 (iop->flags & RDR_IOCTL_FLAG_CLEANED))
360 RDR_DestroyIoctl(iop);
362 lock_ReleaseWrite(&RDR_globalIoctlLock);
365 /* called from RDR_ReceiveCoreRead when we receive a read on the ioctl fid */
367 RDR_IoctlRead(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer, ULONG *pBytesProcessed, afs_uint32 pflags)
373 iop = RDR_FindIoctl(RequestId);
375 return CM_ERROR_BADFD;
377 /* turn the connection around, if required */
378 code = RDR_IoctlPrepareRead(iop, userp, pflags);
381 count = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
382 if (BufferLength < count)
383 count = BufferLength;
385 /* now copy the data into the response packet */
386 memcpy((char *)MappedBuffer, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
388 /* and adjust the counters */
389 iop->ioctl.outCopied += count;
391 *pBytesProcessed = count;
393 RDR_ReleaseIoctl(iop);
398 /* called from RDR_PioctWrite when we receive a write call on the IOCTL
402 RDR_IoctlWrite(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer)
407 iop = RDR_FindIoctl(RequestId);
409 return CM_ERROR_BADFD;
411 RDR_IoctlPrepareWrite(iop);
413 if (BufferLength + iop->ioctl.inCopied > CM_IOCTL_MAXDATA) {
414 code = CM_ERROR_TOOBIG;
419 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, (char *)MappedBuffer, BufferLength);
422 iop->ioctl.inCopied += BufferLength;
425 RDR_ReleaseIoctl(iop);
430 /* parse the passed-in file name and do a namei on it. If we fail,
431 * return an error code, otherwise return the vnode located in *scpp.
433 #define CM_PARSE_FLAG_LITERAL 1
436 RDR_ParseIoctlPath(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
437 cm_scache_t **scpp, afs_uint32 flags)
440 cm_scache_t *substRootp = NULL;
441 cm_scache_t *iscp = NULL;
443 wchar_t *relativePath = NULL;
444 wchar_t *lastComponent = NULL;
445 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
446 int free_path = FALSE;
448 inPath = ioctlp->ioctl.inDatap;
449 /* setup the next data value for the caller to use */
450 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;;
452 osi_Log1(afsd_logp, "RDR_ParseIoctlPath inPath %s", osi_LogSaveString(afsd_logp,inPath));
454 /* This is usually the file name, but for StatMountPoint it is the path. */
455 /* ioctlp->inDatap can be either of the form:
458 * \\netbios-name\submount\path\.
459 * \\netbios-name\submount\path\file
462 /* We do not perform path name translation on the ioctl path data
463 * because these paths were not translated by Windows through the
464 * file system API. Therefore, they are not OEM characters but
465 * whatever the display character set is.
468 // TranslateExtendedChars(relativePath);
470 /* This is usually nothing, but for StatMountPoint it is the file name. */
471 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
473 /* If the string starts with our UTF-8 prefix (which is the
474 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
475 strings), we assume that the provided path is UTF-8. Otherwise
476 we have to convert the string to UTF-8, since that is what we
477 want to use everywhere else.*/
479 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
480 /* String is UTF-8 */
481 inPath += utf8_prefix_size;
482 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
484 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
485 osi_Log1(afsd_logp, "RDR_ParseIoctlPath UTF8 relativePath %S",
486 osi_LogSaveStringW(afsd_logp,relativePath));
489 /* Not a UTF-8 string */
490 /* TODO: If this is an OEM string, we should convert it to UTF-8. */
491 if (smb_StoreAnsiFilenames) {
492 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
496 relativePath = malloc(cch * sizeof(clientchar_t));
497 cm_AnsiToClientString(inPath, -1, relativePath, cch);
499 TranslateExtendedChars(inPath);
501 cch = cm_OemToClientString(inPath, -1, NULL, 0);
505 relativePath = malloc(cch * sizeof(clientchar_t));
506 cm_OemToClientString(inPath, -1, relativePath, cch);
508 osi_Log1(afsd_logp, "RDR_ParseIoctlPath ASCII relativePath %S",
509 osi_LogSaveStringW(afsd_logp,relativePath));
512 if (relativePath[0] == relativePath[1] &&
513 relativePath[1] == '\\' &&
514 !cm_ClientStrCmpNI(RDR_UNCName,relativePath+2,(int)wcslen(RDR_UNCName)))
516 wchar_t shareName[256];
521 /* We may have found a UNC path.
522 * If the first component is the RDR UNC Name,
523 * then throw out the second component (the submount)
524 * since it had better expand into the value of ioctl->tidPathp
526 p = relativePath + 2 + wcslen(RDR_UNCName) + 1; /* buffer overflow vuln.? */
527 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
530 for (i = 0; *p && *p != '\\'; i++,p++ ) {
533 p++; /* skip past trailing slash */
534 shareName[i] = 0; /* terminate string */
536 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
538 /* we found a sharename, therefore use the resulting path */
539 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
540 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
541 userp, NULL, reqp, &substRootp);
544 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [1] code 0x%x", code);
550 lastComponent = cm_ClientStrRChr(p, '\\');
551 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
552 *lastComponent = '\0';
555 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
556 userp, NULL, reqp, &iscp);
558 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
559 userp, NULL, reqp, scpp);
561 cm_ReleaseSCache(iscp);
563 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
564 userp, NULL, reqp, scpp);
566 cm_ReleaseSCache(substRootp);
568 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [2] code 0x%x", code);
574 /* otherwise, treat the name as a cellname mounted off the afs root.
575 * This requires that we reconstruct the shareName string with
576 * leading and trailing slashes.
578 p = relativePath + 2 + wcslen(RDR_UNCName) + 1;
579 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
583 for (i = 1; *p && *p != '\\'; i++,p++ ) {
586 p++; /* skip past trailing slash */
587 shareName[i++] = '/'; /* add trailing slash */
588 shareName[i] = 0; /* terminate string */
591 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
592 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
593 userp, NULL, reqp, &substRootp);
595 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [3] code 0x%x", code);
601 lastComponent = cm_ClientStrRChr(p, '\\');
602 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
603 *lastComponent = '\0';
606 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
607 userp, NULL, reqp, &iscp);
609 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
610 userp, NULL, reqp, scpp);
612 cm_ReleaseSCache(iscp);
614 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
615 userp, NULL, reqp, scpp);
619 cm_ReleaseSCache(substRootp);
620 osi_Log1(afsd_logp,"RDR_ParseIoctlPath code [4] 0x%x", code);
627 code = cm_GetSCache(&ioctlp->parentFid, NULL, &substRootp, userp, reqp);
629 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [6] code 0x%x", code);
635 lastComponent = cm_ClientStrRChr(relativePath, '\\');
636 if (lastComponent && (lastComponent - relativePath) > 1 && wcslen(lastComponent) > 1) {
637 *lastComponent = '\0';
640 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
641 userp, NULL, reqp, &iscp);
643 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
644 userp, NULL, reqp, scpp);
646 cm_ReleaseSCache(iscp);
648 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
649 userp, NULL, reqp, scpp);
652 cm_ReleaseSCache(substRootp);
653 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [7] code 0x%x", code);
661 cm_ReleaseSCache(substRootp);
666 /* Ensure that the status object is up to date */
667 lock_ObtainWrite(&(*scpp)->rw);
668 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
669 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
671 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
672 lock_ReleaseWrite(&(*scpp)->rw);
674 /* and return success */
675 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [8] code 0x%x", code);
681 #define LEAF_SIZE 256
682 /* parse the passed-in file name and do a namei on its parent. If we fail,
683 * return an error code, otherwise return the vnode located in *scpp.
686 RDR_ParseIoctlParent(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
687 cm_scache_t **scpp, wchar_t *leafp)
690 clientchar_t tbuffer[1024];
691 clientchar_t *tp, *jp;
692 cm_scache_t *substRootp = NULL;
693 clientchar_t *inpathp;
695 int free_path = FALSE;
697 inpathdatap = ioctlp->ioctl.inDatap;
699 /* If the string starts with our UTF-8 prefix (which is the
700 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
701 strings), we assume that the provided path is UTF-8. Otherwise
702 we have to convert the string to UTF-8, since that is what we
703 want to use everywhere else.*/
705 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
706 /* String is UTF-8 */
707 inpathdatap += utf8_prefix_size;
708 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
710 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
711 osi_Log1(afsd_logp, "RDR_ParseIoctlParent UTF8 inpathp %S",
712 osi_LogSaveStringW(afsd_logp, inpathp));
716 /* Not a UTF-8 string */
717 /* TODO: If this is an OEM string, we should convert it to
719 if (smb_StoreAnsiFilenames) {
720 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
724 inpathp = malloc(cch * sizeof(clientchar_t));
725 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
727 TranslateExtendedChars(inpathdatap);
729 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
733 inpathp = malloc(cch * sizeof(clientchar_t));
734 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
736 osi_Log1(afsd_logp, "RDR_ParseIoctlParent ASCII inpathp %S",
737 osi_LogSaveStringW(afsd_logp, inpathp));
740 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
741 tp = cm_ClientStrRChr(tbuffer, '\\');
742 jp = cm_ClientStrRChr(tbuffer, '/');
745 else if (jp && (tp - tbuffer) < (jp - tbuffer))
748 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
750 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
755 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
760 inpathp = NULL; /* We don't need this from this point on */
762 if (tbuffer[0] == tbuffer[1] &&
763 tbuffer[1] == '\\' &&
764 !cm_ClientStrCmpNI(RDR_UNCName,tbuffer+2, (int)wcslen(RDR_UNCName)))
766 wchar_t shareName[256];
770 /* We may have found a UNC path.
771 * If the first component is the UNC Name,
772 * then throw out the second component (the submount)
773 * since it had better expand into the value of ioctl->tidPathp
776 p = tbuffer + 2 + cm_ClientStrLen(RDR_UNCName) + 1;
777 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
780 for (i = 0; *p && *p != '\\'; i++,p++ ) {
783 p++; /* skip past trailing slash */
784 shareName[i] = 0; /* terminate string */
786 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
788 /* we found a sharename, therefore use the resulting path */
789 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
790 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
791 userp, NULL, reqp, &substRootp);
794 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [1] code 0x%x", code);
797 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
798 userp, NULL, reqp, scpp);
799 cm_ReleaseSCache(substRootp);
801 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [2] code 0x%x", code);
805 /* otherwise, treat the name as a cellname mounted off the afs root.
806 * This requires that we reconstruct the shareName string with
807 * leading and trailing slashes.
809 p = tbuffer + 2 + wcslen(RDR_UNCName) + 1;
810 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
814 for (i = 1; *p && *p != '\\'; i++,p++ ) {
817 p++; /* skip past trailing slash */
818 shareName[i++] = '/'; /* add trailing slash */
819 shareName[i] = 0; /* terminate string */
821 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
822 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
823 userp, NULL, reqp, &substRootp);
825 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [3] code 0x%x", code);
828 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
829 userp, NULL, reqp, scpp);
830 cm_ReleaseSCache(substRootp);
832 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [4] code 0x%x", code);
837 code = cm_GetSCache(&ioctlp->rootFid, NULL, &substRootp, userp, reqp);
839 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [5] code 0x%x", code);
842 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
843 userp, NULL, reqp, scpp);
844 cm_ReleaseSCache(substRootp);
846 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [6] code 0x%x", code);
851 /* # of bytes of path */
852 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
853 ioctlp->ioctl.inDatap += code;
855 /* Ensure that the status object is up to date */
856 lock_ObtainWrite(&(*scpp)->rw);
857 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
858 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
860 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
861 lock_ReleaseWrite(&(*scpp)->rw);
863 /* and return success */
864 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [7] code 0x%x", code);
869 RDR_IoctlSetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
876 struct ClearToken ct;
882 wchar_t *smbname = NULL;
883 wchar_t *uname = NULL;
885 int release_userp = 0;
887 saveDataPtr = ioctlp->ioctl.inDatap;
889 cm_SkipIoctlPath(&ioctlp->ioctl);
891 tp = ioctlp->ioctl.inDatap;
894 memcpy(&ticketLen, tp, sizeof(ticketLen));
895 tp += sizeof(ticketLen);
896 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN) {
897 code = CM_ERROR_INVAL;
901 /* remember ticket and skip over it for now */
905 /* clear token size */
906 memcpy(&ctSize, tp, sizeof(ctSize));
907 tp += sizeof(ctSize);
908 if (ctSize != sizeof(struct ClearToken)) {
909 code = CM_ERROR_INVAL;
914 memcpy(&ct, tp, ctSize);
916 if (ct.AuthHandle == -1)
917 ct.AuthHandle = 999; /* more rxvab compat stuff */
919 /* more stuff, if any */
920 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
921 /* flags: logon flag */
922 memcpy(&flags, tp, sizeof(int));
926 cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
928 code = CM_ERROR_NOSUCHCELL;
931 tp += strlen(tp) + 1;
934 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
935 tp += strlen(tp) + 1;
937 if (flags & PIOCTL_LOGON) {
938 /* SMB user name with which to associate tokens */
939 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
940 tp += strlen(tp) + 1;
941 osi_Log2(afsd_logp,"RDR_IoctlSetToken for user [%S] smbname [%S]",
942 osi_LogSaveStringW(afsd_logp,uname),
943 osi_LogSaveStringW(afsd_logp,smbname));
945 osi_Log1(afsd_logp,"RDR_IoctlSetToken for user [%S]",
946 osi_LogSaveStringW(afsd_logp, uname));
950 memcpy(&uuid, tp, sizeof(uuid));
951 if (!cm_FindTokenEvent(uuid, sessionKey, NULL)) {
952 code = CM_ERROR_INVAL;
956 #if defined(NO_AUTH_GROUPS)
957 /* after obtaining the session key check whether we can use it */
958 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
959 code = CM_ERROR_NOACCESS;
964 cellp = cm_data.rootCellp;
965 osi_Log0(afsd_logp,"cm_IoctlSetToken - no name specified");
968 #if defined(NO_AUTH_GROUPS)
969 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
971 DWORD dwSize1, dwSize2;
972 wchar_t *pszRefDomain = NULL;
973 SID_NAME_USE snu = SidTypeGroup;
974 clientchar_t * secSidString = NULL;
976 static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
978 if ( cname[0] == '\0') {
979 int len = MAX_COMPUTERNAME_LENGTH+1;
980 GetComputerNameW(cname, &len);
985 * The input name is probably not a SID for the user which is how
986 * the user is now being identified as a result of the SMB
987 * extended authentication. See if we can obtain the SID for the
988 * specified name. If we can, use that instead of the name
992 dwSize1 = dwSize2 = 0;
993 LookupAccountNameW( NULL /* System Name to begin Search */,
998 gle = GetLastError();
999 if (gle == ERROR_INSUFFICIENT_BUFFER) {
1000 pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1002 * Although dwSize2 is supposed to include the terminating
1003 * NUL character, on Win7 it does not.
1005 pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1008 if ( pSid && pszRefDomain ) {
1009 if (LookupAccountNameW( NULL /* System Name to begin Search */,
1012 pszRefDomain, &dwSize2,
1014 ConvertSidToStringSidW(pSid, &secSidString);
1018 userp = smb_FindCMUserBySID( secSidString, cname,
1019 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1020 LocalFree(secSidString);
1027 if (!ConvertStringSidToSidW( smbname, &pSid)) {
1028 userp = smb_FindCMUserBySID( smbname, cname,
1029 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1031 userp = smb_FindCMUserByName( smbname, cname,
1032 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1045 /* store the token */
1046 lock_ObtainMutex(&userp->mx);
1047 ucellp = cm_GetUCell(userp, cellp);
1048 osi_Log1(afsd_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1049 ucellp->ticketLen = ticketLen;
1050 if (ucellp->ticketp)
1051 free(ucellp->ticketp); /* Discard old token if any */
1052 ucellp->ticketp = malloc(ticketLen);
1053 memcpy(ucellp->ticketp, ticket, ticketLen);
1055 * Get the session key from the RPC, rather than from the pioctl.
1058 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1060 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1061 ucellp->kvno = ct.AuthHandle;
1062 ucellp->expirationTime = ct.EndTimestamp;
1065 ucellp->uid = ANONYMOUSID;
1068 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1070 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1073 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1074 lock_ReleaseMutex(&userp->mx);
1076 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1077 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1080 cm_ResetACLCache(cellp, userp);
1083 SecureZeroMemory(sessionKey, sizeof(sessionKey));
1086 cm_ReleaseUser(userp);
1098 RDR_IoctlGetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1102 cm_ioctlQueryOptions_t *optionsp;
1103 afs_uint32 flags = 0;
1105 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1106 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1107 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1109 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1111 cm_SkipIoctlPath(&ioctlp->ioctl);
1112 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1113 optionsp->fid.vnode, optionsp->fid.unique);
1114 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1116 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1121 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1123 cm_ReleaseSCache(scp);
1128 RDR_IoctlSetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1133 afs_uint32 flags = 0;
1135 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1139 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1141 cm_ReleaseSCache(scp);
1146 RDR_IoctlGetFileCellName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1150 cm_ioctlQueryOptions_t *optionsp;
1151 afs_uint32 flags = 0;
1153 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1154 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1155 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1157 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1159 cm_SkipIoctlPath(&ioctlp->ioctl);
1160 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1161 optionsp->fid.vnode, optionsp->fid.unique);
1162 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1164 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1169 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1171 cm_ReleaseSCache(scp);
1177 RDR_IoctlFlushAllVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1179 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1181 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &ioctlp->req);
1185 RDR_IoctlFlushVolume(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1189 cm_ioctlQueryOptions_t *optionsp;
1190 afs_uint32 flags = 0;
1192 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1193 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1194 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1196 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1198 cm_SkipIoctlPath(&ioctlp->ioctl);
1199 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1200 optionsp->fid.vnode, optionsp->fid.unique);
1201 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1203 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1208 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1210 cm_ReleaseSCache(scp);
1216 RDR_IoctlFlushFile(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1220 cm_ioctlQueryOptions_t *optionsp;
1221 afs_uint32 flags = 0;
1223 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1224 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1225 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1227 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1229 cm_SkipIoctlPath(&ioctlp->ioctl);
1230 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1231 optionsp->fid.vnode, optionsp->fid.unique);
1232 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1234 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1239 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1241 cm_ReleaseSCache(scp);
1246 RDR_IoctlSetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1251 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, 0);
1252 if (code) return code;
1254 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1255 cm_ReleaseSCache(scp);
1261 RDR_IoctlGetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1265 cm_ioctlQueryOptions_t *optionsp;
1266 afs_uint32 flags = 0;
1268 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1269 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1270 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1272 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1274 cm_SkipIoctlPath(&ioctlp->ioctl);
1275 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1276 optionsp->fid.vnode, optionsp->fid.unique);
1277 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1279 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1284 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1286 cm_ReleaseSCache(scp);
1292 RDR_IoctlGetFid(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1296 cm_ioctlQueryOptions_t * optionsp;
1297 afs_uint32 flags = 0;
1299 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1300 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1301 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1303 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1307 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1309 cm_ReleaseSCache(scp);
1315 RDR_IoctlGetFileType(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1319 cm_ioctlQueryOptions_t * optionsp;
1320 afs_uint32 flags = 0;
1322 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1323 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1324 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1326 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1328 cm_SkipIoctlPath(&ioctlp->ioctl);
1329 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1330 optionsp->fid.vnode, optionsp->fid.unique);
1331 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1333 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1338 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1340 cm_ReleaseSCache(scp);
1346 RDR_IoctlGetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1350 cm_ioctlQueryOptions_t *optionsp;
1351 afs_uint32 flags = 0;
1353 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1354 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1355 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1357 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1359 cm_SkipIoctlPath(&ioctlp->ioctl);
1360 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1361 optionsp->fid.vnode, optionsp->fid.unique);
1362 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1364 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1369 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1371 cm_ReleaseSCache(scp);
1377 RDR_IoctlWhereIs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1381 cm_ioctlQueryOptions_t *optionsp;
1382 afs_uint32 flags = 0;
1384 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1385 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1386 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1388 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1390 cm_SkipIoctlPath(&ioctlp->ioctl);
1391 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1392 optionsp->fid.vnode, optionsp->fid.unique);
1393 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1395 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1400 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1402 cm_ReleaseSCache(scp);
1409 RDR_IoctlStatMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1414 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &dscp, 0);
1418 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &ioctlp->req);
1420 cm_ReleaseSCache(dscp);
1426 RDR_IoctlDeleteMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1431 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &dscp, 0);
1435 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &ioctlp->req);
1437 cm_ReleaseSCache(dscp);
1443 RDR_IoctlCheckServers(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1445 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1447 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1451 RDR_IoctlGag(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1453 /* we don't print anything superfluous, so we don't support the gag call */
1454 return CM_ERROR_INVAL;
1458 RDR_IoctlCheckVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1460 cm_SkipIoctlPath(&ioctlp->ioctl);
1462 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1465 afs_int32 RDR_IoctlSetCacheSize(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1467 cm_SkipIoctlPath(&ioctlp->ioctl);
1469 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1474 RDR_IoctlTraceControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1476 cm_SkipIoctlPath(&ioctlp->ioctl);
1478 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1482 RDR_IoctlGetCacheParms(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1484 cm_SkipIoctlPath(&ioctlp->ioctl);
1486 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1490 RDR_IoctlGetCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1492 cm_SkipIoctlPath(&ioctlp->ioctl);
1494 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1498 RDR_IoctlNewCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1500 cm_SkipIoctlPath(&ioctlp->ioctl);
1502 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1506 RDR_IoctlNewCell2(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1508 cm_SkipIoctlPath(&ioctlp->ioctl);
1510 return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1514 RDR_IoctlGetWsCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1516 cm_SkipIoctlPath(&ioctlp->ioctl);
1518 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1522 RDR_IoctlSysName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1524 cm_SkipIoctlPath(&ioctlp->ioctl);
1526 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1530 RDR_IoctlGetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1532 cm_SkipIoctlPath(&ioctlp->ioctl);
1534 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1538 RDR_IoctlSetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1540 cm_SkipIoctlPath(&ioctlp->ioctl);
1542 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1546 RDR_IoctlSetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1548 cm_SkipIoctlPath(&ioctlp->ioctl);
1550 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1554 RDR_IoctlGetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1556 cm_SkipIoctlPath(&ioctlp->ioctl);
1558 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1562 RDR_IoctlStoreBehind(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1564 /* we ignore default asynchrony since we only have one way
1565 * of doing this today.
1571 RDR_IoctlCreateMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1575 wchar_t leaf[LEAF_SIZE];
1577 code = RDR_ParseIoctlParent(ioctlp, userp, &ioctlp->req, &dscp, leaf);
1581 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &ioctlp->req, leaf);
1583 cm_ReleaseSCache(dscp);
1588 RDR_IoctlSymlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1592 wchar_t leaf[LEAF_SIZE];
1594 code = RDR_ParseIoctlParent(ioctlp, userp, &ioctlp->req, &dscp, leaf);
1595 if (code) return code;
1597 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &ioctlp->req, leaf);
1599 cm_ReleaseSCache(dscp);
1605 RDR_IoctlListlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1610 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &dscp, 0);
1611 if (code) return code;
1613 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &ioctlp->req);
1615 cm_ReleaseSCache(dscp);
1620 RDR_IoctlIslink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1621 {/*CHECK FOR VALID SYMLINK*/
1625 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &dscp, 0);
1626 if (code) return code;
1628 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &ioctlp->req);
1630 cm_ReleaseSCache(dscp);
1636 RDR_IoctlDeletelink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1641 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &dscp, 0);
1642 if (code) return code;
1644 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &ioctlp->req);
1646 cm_ReleaseSCache(dscp);
1652 RDR_IoctlGetTokenIter(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1654 cm_SkipIoctlPath(&ioctlp->ioctl);
1656 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1660 RDR_IoctlGetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1662 cm_SkipIoctlPath(&ioctlp->ioctl);
1664 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1669 RDR_IoctlDelToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1671 cm_SkipIoctlPath(&ioctlp->ioctl);
1673 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1678 RDR_IoctlDelAllToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1680 cm_SkipIoctlPath(&ioctlp->ioctl);
1682 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1687 RDR_IoctlMakeSubmount(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1689 cm_SkipIoctlPath(&ioctlp->ioctl);
1691 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1695 RDR_IoctlGetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1697 cm_SkipIoctlPath(&ioctlp->ioctl);
1699 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1703 RDR_IoctlSetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1705 cm_SkipIoctlPath(&ioctlp->ioctl);
1707 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1711 RDR_IoctlRxStatProcess(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1713 cm_SkipIoctlPath(&ioctlp->ioctl);
1715 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1720 RDR_IoctlRxStatPeer(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1722 cm_SkipIoctlPath(&ioctlp->ioctl);
1724 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1728 RDR_IoctlUnicodeControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1730 cm_SkipIoctlPath(&ioctlp->ioctl);
1732 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1736 RDR_IoctlUUIDControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1738 cm_SkipIoctlPath(&ioctlp->ioctl);
1740 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1745 RDR_IoctlMemoryDump(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1747 cm_SkipIoctlPath(&ioctlp->ioctl);
1749 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1753 RDR_IoctlPathAvailability(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1757 cm_ioctlQueryOptions_t *optionsp;
1758 afs_uint32 flags = 0;
1760 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1761 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1762 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1764 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1766 cm_SkipIoctlPath(&ioctlp->ioctl);
1767 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1768 optionsp->fid.vnode, optionsp->fid.unique);
1769 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1771 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1776 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1777 cm_ReleaseSCache(scp);
1782 RDR_IoctlVolStatTest(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1784 cm_SkipIoctlPath(&ioctlp->ioctl);
1786 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &ioctlp->req);
1792 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1796 RDR_IoctlSetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1800 cm_ioctlQueryOptions_t *optionsp;
1801 afs_uint32 flags = 0;
1803 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1805 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1806 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1808 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1810 cm_SkipIoctlPath(&ioctlp->ioctl);
1811 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1812 optionsp->fid.vnode, optionsp->fid.unique);
1813 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1815 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1820 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1823 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1825 cm_ReleaseSCache(scp);
1833 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1837 RDR_IoctlSetGroup(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1841 cm_ioctlQueryOptions_t *optionsp;
1842 afs_uint32 flags = 0;
1844 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1846 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1847 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1849 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1851 cm_SkipIoctlPath(&ioctlp->ioctl);
1852 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1853 optionsp->fid.vnode, optionsp->fid.unique);
1854 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1856 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1861 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1864 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1866 cm_ReleaseSCache(scp);
1872 RDR_IoctlGetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1876 cm_ioctlQueryOptions_t *optionsp;
1877 afs_uint32 flags = 0;
1879 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1880 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1881 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1883 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1885 cm_SkipIoctlPath(&ioctlp->ioctl);
1886 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1887 optionsp->fid.vnode, optionsp->fid.unique);
1888 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1890 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1895 code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1897 cm_ReleaseSCache(scp);
1905 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1909 RDR_IoctlSetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1913 cm_ioctlQueryOptions_t *optionsp;
1914 afs_uint32 flags = 0;
1916 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1918 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1919 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1921 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1923 cm_SkipIoctlPath(&ioctlp->ioctl);
1924 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1925 optionsp->fid.vnode, optionsp->fid.unique);
1926 code = cm_GetSCache(&fid, NULL, &scp, userp, &ioctlp->req);
1928 code = RDR_ParseIoctlPath(ioctlp, userp, &ioctlp->req, &scp, flags);
1933 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1936 code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &ioctlp->req);
1938 cm_ReleaseSCache(scp);
1944 RDR_IoctlGetVerifyData(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1946 cm_SkipIoctlPath(&ioctlp->ioctl);
1948 return cm_IoctlGetVerifyData(&ioctlp->ioctl);
1952 RDR_IoctlSetVerifyData(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1954 cm_SkipIoctlPath(&ioctlp->ioctl);
1956 return cm_IoctlSetVerifyData(&ioctlp->ioctl);