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)
161 lock_ObtainWrite(&RDR_globalIoctlLock);
162 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
163 if (iop->index == index)
170 /* we are reusing a previous ioctl */
171 if (cm_FidCmp(&iop->parentFid, parentFid)) {
172 iop->parentFid = *parentFid;
173 if (iop->parentScp) {
174 cm_ReleaseSCache(iop->parentScp);
175 iop->parentScp = NULL;
177 cm_GetSCache(parentFid, NULL, &iop->parentScp, userp, &req);
178 iop->rootFid = *rootFid;
181 /* need to allocate a new one */
182 iop = malloc(sizeof(*iop));
183 memset(iop, 0, sizeof(*iop));
184 if (RDR_allIoctls == NULL)
185 RDR_allIoctls = RDR_allIoctlsLast = iop;
187 iop->prev = RDR_allIoctlsLast;
188 RDR_allIoctlsLast->next = iop;
189 RDR_allIoctlsLast = iop;
192 if (parentFid->cell == 0) {
193 iop->parentFid = cm_data.rootFid;
194 iop->parentScp = cm_RootSCachep(userp, &req);
195 cm_HoldSCache(iop->parentScp);
197 iop->parentFid = *parentFid;
198 cm_GetSCache(parentFid, NULL, &iop->parentScp, userp, &req);
200 if (rootFid->cell == 0) {
201 iop->rootFid = cm_data.rootFid;
203 iop->rootFid = *rootFid;
206 lock_ReleaseWrite(&RDR_globalIoctlLock);
210 RDR_DestroyIoctl(RDR_ioctl_t *iop)
216 cm_ReleaseSCache(iop->parentScp);
218 if (iop->ioctl.inAllocp)
219 free(iop->ioctl.inAllocp);
220 if (iop->ioctl.outAllocp)
221 free(iop->ioctl.outAllocp);
223 if (RDR_allIoctls == RDR_allIoctlsLast)
224 RDR_allIoctls = RDR_allIoctlsLast = NULL;
226 if (iop->prev == NULL)
227 RDR_allIoctls = iop->next;
229 iop->prev->next = iop->next;
230 if (iop->next == NULL) {
231 RDR_allIoctlsLast = iop->prev;
232 iop->prev->next = NULL;
234 iop->next->prev = iop->prev;
240 RDR_CleanupIoctl(ULONG index)
244 lock_ObtainWrite(&RDR_globalIoctlLock);
245 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
246 if (iop->index == index)
251 if (iop->refCount == 0) {
252 RDR_DestroyIoctl(iop);
256 iop->flags |= RDR_IOCTL_FLAG_CLEANED;
259 lock_ReleaseWrite(&RDR_globalIoctlLock);
262 /* called when we receive a write call. If this is the first write call after
263 * a series of reads (or the very first call), then we start a new call.
264 * We also ensure that things are properly initialized for the start of a call.
267 RDR_IoctlPrepareWrite(RDR_ioctl_t *ioctlp)
269 /* make sure the buffer(s) are allocated */
270 if (!ioctlp->ioctl.inAllocp)
271 ioctlp->ioctl.inAllocp = malloc(CM_IOCTL_MAXDATA);
272 if (!ioctlp->ioctl.outAllocp)
273 ioctlp->ioctl.outAllocp = malloc(CM_IOCTL_MAXDATA);
275 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
276 (void) memset(ioctlp->ioctl.inAllocp, 0, CM_IOCTL_MAXDATA);
277 (void) memset(ioctlp->ioctl.outAllocp, 0, CM_IOCTL_MAXDATA);
279 /* and make sure that we've reset our state for the new incoming request */
280 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
281 ioctlp->ioctl.inCopied = 0;
282 ioctlp->ioctl.outCopied = 0;
283 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
284 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
285 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
289 /* called when we receive a read call, does the send of the received data if
290 * this is the first read call. This is the function that actually makes the
291 * call to the ioctl code.
294 RDR_IoctlPrepareRead(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
297 RDR_ioctlProc_t *procp = NULL;
300 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
301 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
303 /* do the call now, or fail if we didn't get an opcode, or
304 * enough of an opcode.
306 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
307 return CM_ERROR_INVAL;
309 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
310 ioctlp->ioctl.inDatap += sizeof(afs_int32);
312 osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode);
314 /* check for opcode out of bounds */
315 if (opcode < 0 || opcode >= CM_IOCTL_MAXPROCS)
316 return CM_ERROR_TOOBIG;
318 /* check for no such proc */
319 procp = RDR_ioctlProcsp[opcode];
321 return CM_ERROR_BADOP;
323 /* otherwise, make the call */
324 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
325 code = (*procp)(ioctlp, userp, pflags);
327 osi_Log1(afsd_logp, "Ioctl return code 0x%x", code);
329 /* copy in return code */
330 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
336 RDR_FindIoctl(ULONG index)
340 lock_ObtainRead(&RDR_globalIoctlLock);
341 for ( iop=RDR_allIoctls; iop; iop=iop->next) {
342 if (iop->index == index &&
343 !(iop->flags & RDR_IOCTL_FLAG_CLEANED)) {
344 InterlockedIncrement(&iop->refCount);
348 lock_ReleaseRead(&RDR_globalIoctlLock);
353 RDR_ReleaseIoctl(RDR_ioctl_t * iop)
355 lock_ObtainWrite(&RDR_globalIoctlLock);
356 InterlockedDecrement(&iop->refCount);
358 if (iop->refCount == 0 &&
359 (iop->flags & RDR_IOCTL_FLAG_CLEANED))
361 RDR_DestroyIoctl(iop);
363 lock_ReleaseWrite(&RDR_globalIoctlLock);
366 /* called from RDR_ReceiveCoreRead when we receive a read on the ioctl fid */
368 RDR_IoctlRead(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer, ULONG *pBytesProcessed, cm_req_t *reqp, afs_uint32 pflags)
374 iop = RDR_FindIoctl(RequestId);
376 return CM_ERROR_BADFD;
378 /* turn the connection around, if required */
379 code = RDR_IoctlPrepareRead(iop, userp, pflags);
382 count = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
383 if (BufferLength < count)
384 count = BufferLength;
386 /* now copy the data into the response packet */
387 memcpy((char *)MappedBuffer, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
389 /* and adjust the counters */
390 iop->ioctl.outCopied += count;
392 *pBytesProcessed = count;
394 RDR_ReleaseIoctl(iop);
399 /* called from RDR_PioctWRite when we receive a write call on the IOCTL
403 RDR_IoctlWrite(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer, cm_req_t *reqp)
408 iop = RDR_FindIoctl(RequestId);
410 return CM_ERROR_BADFD;
412 RDR_IoctlPrepareWrite(iop);
414 if (BufferLength + iop->ioctl.inCopied > CM_IOCTL_MAXDATA) {
415 code = CM_ERROR_TOOBIG;
420 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, (char *)MappedBuffer, BufferLength);
423 iop->ioctl.inCopied += BufferLength;
426 RDR_ReleaseIoctl(iop);
431 /* parse the passed-in file name and do a namei on it. If we fail,
432 * return an error code, otherwise return the vnode located in *scpp.
434 #define CM_PARSE_FLAG_LITERAL 1
437 RDR_ParseIoctlPath(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
438 cm_scache_t **scpp, afs_uint32 flags)
441 cm_scache_t *substRootp = NULL;
442 cm_scache_t *iscp = NULL;
444 wchar_t *relativePath = NULL;
445 wchar_t *lastComponent = NULL;
446 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
447 int free_path = FALSE;
449 inPath = ioctlp->ioctl.inDatap;
450 /* setup the next data value for the caller to use */
451 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;;
453 osi_Log1(afsd_logp, "RDR_ParseIoctlPath inPath %s", osi_LogSaveString(afsd_logp,inPath));
455 /* This is usually the file name, but for StatMountPoint it is the path. */
456 /* ioctlp->inDatap can be either of the form:
459 * \\netbios-name\submount\path\.
460 * \\netbios-name\submount\path\file
463 /* We do not perform path name translation on the ioctl path data
464 * because these paths were not translated by Windows through the
465 * file system API. Therefore, they are not OEM characters but
466 * whatever the display character set is.
469 // TranslateExtendedChars(relativePath);
471 /* This is usually nothing, but for StatMountPoint it is the file name. */
472 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
474 /* If the string starts with our UTF-8 prefix (which is the
475 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
476 strings), we assume that the provided path is UTF-8. Otherwise
477 we have to convert the string to UTF-8, since that is what we
478 want to use everywhere else.*/
480 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
481 /* String is UTF-8 */
482 inPath += utf8_prefix_size;
483 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
485 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
486 osi_Log1(afsd_logp, "RDR_ParseIoctlPath UTF8 relativePath %S",
487 osi_LogSaveStringW(afsd_logp,relativePath));
490 /* Not a UTF-8 string */
491 /* TODO: If this is an OEM string, we should convert it to UTF-8. */
492 if (smb_StoreAnsiFilenames) {
493 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
497 relativePath = malloc(cch * sizeof(clientchar_t));
498 cm_AnsiToClientString(inPath, -1, relativePath, cch);
500 TranslateExtendedChars(inPath);
502 cch = cm_OemToClientString(inPath, -1, NULL, 0);
506 relativePath = malloc(cch * sizeof(clientchar_t));
507 cm_OemToClientString(inPath, -1, relativePath, cch);
509 osi_Log1(afsd_logp, "RDR_ParseIoctlPath ASCII relativePath %S",
510 osi_LogSaveStringW(afsd_logp,relativePath));
513 if (relativePath[0] == relativePath[1] &&
514 relativePath[1] == '\\' &&
515 !cm_ClientStrCmpNI(RDR_UNCName,relativePath+2,(int)wcslen(RDR_UNCName)))
517 wchar_t shareName[256];
522 /* We may have found a UNC path.
523 * If the first component is the RDR UNC Name,
524 * then throw out the second component (the submount)
525 * since it had better expand into the value of ioctl->tidPathp
527 p = relativePath + 2 + wcslen(RDR_UNCName) + 1; /* buffer overflow vuln.? */
528 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
531 for (i = 0; *p && *p != '\\'; i++,p++ ) {
534 p++; /* skip past trailing slash */
535 shareName[i] = 0; /* terminate string */
537 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
539 /* we found a sharename, therefore use the resulting path */
540 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
541 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
542 userp, NULL, reqp, &substRootp);
545 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [1] code 0x%x", code);
551 lastComponent = cm_ClientStrRChr(p, '\\');
552 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
553 *lastComponent = '\0';
556 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
557 userp, NULL, reqp, &iscp);
559 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
560 userp, NULL, reqp, scpp);
562 cm_ReleaseSCache(iscp);
564 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
565 userp, NULL, reqp, scpp);
567 cm_ReleaseSCache(substRootp);
569 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [2] code 0x%x", code);
575 /* otherwise, treat the name as a cellname mounted off the afs root.
576 * This requires that we reconstruct the shareName string with
577 * leading and trailing slashes.
579 p = relativePath + 2 + wcslen(RDR_UNCName) + 1;
580 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
584 for (i = 1; *p && *p != '\\'; i++,p++ ) {
587 p++; /* skip past trailing slash */
588 shareName[i++] = '/'; /* add trailing slash */
589 shareName[i] = 0; /* terminate string */
592 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
593 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
594 userp, NULL, reqp, &substRootp);
596 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [3] code 0x%x", code);
602 lastComponent = cm_ClientStrRChr(p, '\\');
603 if (lastComponent && (lastComponent - p) > 1 && wcslen(lastComponent) > 1) {
604 *lastComponent = '\0';
607 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
608 userp, NULL, reqp, &iscp);
610 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
611 userp, NULL, reqp, scpp);
613 cm_ReleaseSCache(iscp);
615 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
616 userp, NULL, reqp, scpp);
620 cm_ReleaseSCache(substRootp);
621 osi_Log1(afsd_logp,"RDR_ParseIoctlPath code [4] 0x%x", code);
628 code = cm_GetSCache(&ioctlp->parentFid, NULL, &substRootp, userp, reqp);
630 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [6] code 0x%x", code);
636 lastComponent = cm_ClientStrRChr(relativePath, '\\');
637 if (lastComponent && (lastComponent - relativePath) > 1 && wcslen(lastComponent) > 1) {
638 *lastComponent = '\0';
641 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
642 userp, NULL, reqp, &iscp);
644 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
645 userp, NULL, reqp, scpp);
647 cm_ReleaseSCache(iscp);
649 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
650 userp, NULL, reqp, scpp);
653 cm_ReleaseSCache(substRootp);
654 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [7] code 0x%x", code);
662 cm_ReleaseSCache(substRootp);
667 /* Ensure that the status object is up to date */
668 lock_ObtainWrite(&(*scpp)->rw);
669 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
670 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
672 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
673 lock_ReleaseWrite(&(*scpp)->rw);
675 /* and return success */
676 osi_Log1(afsd_logp,"RDR_ParseIoctlPath [8] code 0x%x", code);
682 #define LEAF_SIZE 256
683 /* parse the passed-in file name and do a namei on its parent. If we fail,
684 * return an error code, otherwise return the vnode located in *scpp.
687 RDR_ParseIoctlParent(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
688 cm_scache_t **scpp, wchar_t *leafp)
691 clientchar_t tbuffer[1024];
692 clientchar_t *tp, *jp;
693 cm_scache_t *substRootp = NULL;
694 clientchar_t *inpathp;
696 int free_path = FALSE;
698 inpathdatap = ioctlp->ioctl.inDatap;
700 /* If the string starts with our UTF-8 prefix (which is the
701 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
702 strings), we assume that the provided path is UTF-8. Otherwise
703 we have to convert the string to UTF-8, since that is what we
704 want to use everywhere else.*/
706 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
707 /* String is UTF-8 */
708 inpathdatap += utf8_prefix_size;
709 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
711 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
712 osi_Log1(afsd_logp, "RDR_ParseIoctlParent UTF8 inpathp %S",
713 osi_LogSaveStringW(afsd_logp, inpathp));
717 /* Not a UTF-8 string */
718 /* TODO: If this is an OEM string, we should convert it to
720 if (smb_StoreAnsiFilenames) {
721 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
725 inpathp = malloc(cch * sizeof(clientchar_t));
726 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
728 TranslateExtendedChars(inpathdatap);
730 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
734 inpathp = malloc(cch * sizeof(clientchar_t));
735 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
737 osi_Log1(afsd_logp, "RDR_ParseIoctlParent ASCII inpathp %S",
738 osi_LogSaveStringW(afsd_logp, inpathp));
741 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
742 tp = cm_ClientStrRChr(tbuffer, '\\');
743 jp = cm_ClientStrRChr(tbuffer, '/');
746 else if (jp && (tp - tbuffer) < (jp - tbuffer))
749 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
751 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
756 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
761 inpathp = NULL; /* We don't need this from this point on */
763 if (tbuffer[0] == tbuffer[1] &&
764 tbuffer[1] == '\\' &&
765 !cm_ClientStrCmpNI(RDR_UNCName,tbuffer+2, (int)wcslen(RDR_UNCName)))
767 wchar_t shareName[256];
771 /* We may have found a UNC path.
772 * If the first component is the UNC Name,
773 * then throw out the second component (the submount)
774 * since it had better expand into the value of ioctl->tidPathp
777 p = tbuffer + 2 + cm_ClientStrLen(RDR_UNCName) + 1;
778 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
781 for (i = 0; *p && *p != '\\'; i++,p++ ) {
784 p++; /* skip past trailing slash */
785 shareName[i] = 0; /* terminate string */
787 shareFound = smb_FindShare(NULL, NULL, shareName, &sharePath);
789 /* we found a sharename, therefore use the resulting path */
790 code = cm_NameI(cm_RootSCachep(userp, reqp), sharePath,
791 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
792 userp, NULL, reqp, &substRootp);
795 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [1] code 0x%x", code);
798 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
799 userp, NULL, reqp, scpp);
800 cm_ReleaseSCache(substRootp);
802 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [2] code 0x%x", code);
806 /* otherwise, treat the name as a cellname mounted off the afs root.
807 * This requires that we reconstruct the shareName string with
808 * leading and trailing slashes.
810 p = tbuffer + 2 + wcslen(RDR_UNCName) + 1;
811 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
815 for (i = 1; *p && *p != '\\'; i++,p++ ) {
818 p++; /* skip past trailing slash */
819 shareName[i++] = '/'; /* add trailing slash */
820 shareName[i] = 0; /* terminate string */
822 code = cm_NameI(cm_RootSCachep(userp, reqp), shareName,
823 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
824 userp, NULL, reqp, &substRootp);
826 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [3] code 0x%x", code);
829 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
830 userp, NULL, reqp, scpp);
831 cm_ReleaseSCache(substRootp);
833 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [4] code 0x%x", code);
838 code = cm_GetSCache(&ioctlp->rootFid, NULL, &substRootp, userp, reqp);
840 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [5] code 0x%x", code);
843 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
844 userp, NULL, reqp, scpp);
845 cm_ReleaseSCache(substRootp);
847 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [6] code 0x%x", code);
852 /* # of bytes of path */
853 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
854 ioctlp->ioctl.inDatap += code;
856 /* Ensure that the status object is up to date */
857 lock_ObtainWrite(&(*scpp)->rw);
858 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
859 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
861 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
862 lock_ReleaseWrite(&(*scpp)->rw);
864 /* and return success */
865 osi_Log1(afsd_logp,"RDR_ParseIoctlParent [7] code 0x%x", code);
870 RDR_IoctlSetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
877 struct ClearToken ct;
883 wchar_t *smbname = NULL;
884 wchar_t *uname = NULL;
886 int release_userp = 0;
888 saveDataPtr = ioctlp->ioctl.inDatap;
890 cm_SkipIoctlPath(&ioctlp->ioctl);
892 tp = ioctlp->ioctl.inDatap;
895 memcpy(&ticketLen, tp, sizeof(ticketLen));
896 tp += sizeof(ticketLen);
897 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN) {
898 code = CM_ERROR_INVAL;
902 /* remember ticket and skip over it for now */
906 /* clear token size */
907 memcpy(&ctSize, tp, sizeof(ctSize));
908 tp += sizeof(ctSize);
909 if (ctSize != sizeof(struct ClearToken)) {
910 code = CM_ERROR_INVAL;
915 memcpy(&ct, tp, ctSize);
917 if (ct.AuthHandle == -1)
918 ct.AuthHandle = 999; /* more rxvab compat stuff */
920 /* more stuff, if any */
921 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
922 /* flags: logon flag */
923 memcpy(&flags, tp, sizeof(int));
927 cellp = cm_GetCell(tp, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
929 code = CM_ERROR_NOSUCHCELL;
932 tp += strlen(tp) + 1;
935 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
936 tp += strlen(tp) + 1;
938 if (flags & PIOCTL_LOGON) {
939 /* SMB user name with which to associate tokens */
940 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
941 tp += strlen(tp) + 1;
942 osi_Log2(afsd_logp,"RDR_IoctlSetToken for user [%S] smbname [%S]",
943 osi_LogSaveStringW(afsd_logp,uname),
944 osi_LogSaveStringW(afsd_logp,smbname));
946 osi_Log1(afsd_logp,"RDR_IoctlSetToken for user [%S]",
947 osi_LogSaveStringW(afsd_logp, uname));
951 memcpy(&uuid, tp, sizeof(uuid));
952 if (!cm_FindTokenEvent(uuid, sessionKey, NULL)) {
953 code = CM_ERROR_INVAL;
957 #if defined(NO_AUTH_GROUPS)
958 /* after obtaining the session key check whether we can use it */
959 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
960 code = CM_ERROR_NOACCESS;
965 cellp = cm_data.rootCellp;
966 osi_Log0(afsd_logp,"cm_IoctlSetToken - no name specified");
969 #if defined(NO_AUTH_GROUPS)
970 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
972 DWORD dwSize1, dwSize2;
973 wchar_t *pszRefDomain = NULL;
974 SID_NAME_USE snu = SidTypeGroup;
975 clientchar_t * secSidString = NULL;
977 static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
979 if ( cname[0] == '\0') {
980 int len = MAX_COMPUTERNAME_LENGTH+1;
981 GetComputerNameW(cname, &len);
986 * The input name is probably not a SID for the user which is how
987 * the user is now being identified as a result of the SMB
988 * extended authentication. See if we can obtain the SID for the
989 * specified name. If we can, use that instead of the name
993 dwSize1 = dwSize2 = 0;
994 LookupAccountNameW( NULL /* System Name to begin Search */,
999 gle = GetLastError();
1000 if (gle == ERROR_INSUFFICIENT_BUFFER) {
1001 pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1003 * Although dwSize2 is supposed to include the terminating
1004 * NUL character, on Win7 it does not.
1006 pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1009 if ( pSid && pszRefDomain ) {
1010 if (LookupAccountNameW( NULL /* System Name to begin Search */,
1013 pszRefDomain, &dwSize2,
1015 ConvertSidToStringSidW(pSid, &secSidString);
1019 userp = smb_FindCMUserBySID( secSidString, cname,
1020 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1021 LocalFree(secSidString);
1028 if (!ConvertStringSidToSidW( smbname, &pSid)) {
1029 userp = smb_FindCMUserBySID( smbname, cname,
1030 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1032 userp = smb_FindCMUserByName( smbname, cname,
1033 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1046 /* store the token */
1047 lock_ObtainMutex(&userp->mx);
1048 ucellp = cm_GetUCell(userp, cellp);
1049 osi_Log1(afsd_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1050 ucellp->ticketLen = ticketLen;
1051 if (ucellp->ticketp)
1052 free(ucellp->ticketp); /* Discard old token if any */
1053 ucellp->ticketp = malloc(ticketLen);
1054 memcpy(ucellp->ticketp, ticket, ticketLen);
1056 * Get the session key from the RPC, rather than from the pioctl.
1059 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1061 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1062 ucellp->kvno = ct.AuthHandle;
1063 ucellp->expirationTime = ct.EndTimestamp;
1066 ucellp->uid = ANONYMOUSID;
1069 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1071 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1074 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1075 lock_ReleaseMutex(&userp->mx);
1077 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1078 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1081 cm_ResetACLCache(cellp, userp);
1084 SecureZeroMemory(sessionKey, sizeof(sessionKey));
1087 cm_ReleaseUser(userp);
1099 RDR_IoctlGetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1104 cm_ioctlQueryOptions_t *optionsp;
1105 afs_uint32 flags = 0;
1109 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1110 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1111 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1113 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1115 cm_SkipIoctlPath(&ioctlp->ioctl);
1116 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1117 optionsp->fid.vnode, optionsp->fid.unique);
1118 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1120 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1125 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1127 cm_ReleaseSCache(scp);
1132 RDR_IoctlSetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1138 afs_uint32 flags = 0;
1142 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1146 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1148 cm_ReleaseSCache(scp);
1153 RDR_IoctlGetFileCellName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1158 cm_ioctlQueryOptions_t *optionsp;
1159 afs_uint32 flags = 0;
1163 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1164 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1165 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1167 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1169 cm_SkipIoctlPath(&ioctlp->ioctl);
1170 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1171 optionsp->fid.vnode, optionsp->fid.unique);
1172 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1174 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1179 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1181 cm_ReleaseSCache(scp);
1187 RDR_IoctlFlushAllVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1193 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1195 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1199 RDR_IoctlFlushVolume(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1204 cm_ioctlQueryOptions_t *optionsp;
1205 afs_uint32 flags = 0;
1209 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1210 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1211 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1213 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1215 cm_SkipIoctlPath(&ioctlp->ioctl);
1216 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1217 optionsp->fid.vnode, optionsp->fid.unique);
1218 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1220 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1225 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1227 cm_ReleaseSCache(scp);
1233 RDR_IoctlFlushFile(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1238 cm_ioctlQueryOptions_t *optionsp;
1239 afs_uint32 flags = 0;
1243 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1244 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1245 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1247 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1249 cm_SkipIoctlPath(&ioctlp->ioctl);
1250 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1251 optionsp->fid.vnode, optionsp->fid.unique);
1252 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1254 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1259 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1261 cm_ReleaseSCache(scp);
1266 RDR_IoctlSetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1274 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1275 if (code) return code;
1277 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1278 cm_ReleaseSCache(scp);
1284 RDR_IoctlGetVolumeStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1288 cm_ioctlQueryOptions_t *optionsp;
1289 afs_uint32 flags = 0;
1294 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1295 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1296 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1298 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1300 cm_SkipIoctlPath(&ioctlp->ioctl);
1301 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1302 optionsp->fid.vnode, optionsp->fid.unique);
1303 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1305 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1310 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1312 cm_ReleaseSCache(scp);
1318 RDR_IoctlGetFid(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1323 cm_ioctlQueryOptions_t * optionsp;
1324 afs_uint32 flags = 0;
1328 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1329 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1330 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1332 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1336 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1338 cm_ReleaseSCache(scp);
1344 RDR_IoctlGetFileType(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1349 cm_ioctlQueryOptions_t * optionsp;
1350 afs_uint32 flags = 0;
1354 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1355 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1356 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1358 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1360 cm_SkipIoctlPath(&ioctlp->ioctl);
1361 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1362 optionsp->fid.vnode, optionsp->fid.unique);
1363 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1365 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1370 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1372 cm_ReleaseSCache(scp);
1378 RDR_IoctlGetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1383 cm_ioctlQueryOptions_t *optionsp;
1384 afs_uint32 flags = 0;
1388 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1389 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1390 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1392 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1394 cm_SkipIoctlPath(&ioctlp->ioctl);
1395 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1396 optionsp->fid.vnode, optionsp->fid.unique);
1397 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1399 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1404 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1406 cm_ReleaseSCache(scp);
1412 RDR_IoctlWhereIs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1417 cm_ioctlQueryOptions_t *optionsp;
1418 afs_uint32 flags = 0;
1422 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1423 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1424 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1426 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1428 cm_SkipIoctlPath(&ioctlp->ioctl);
1429 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1430 optionsp->fid.vnode, optionsp->fid.unique);
1431 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1433 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1438 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1440 cm_ReleaseSCache(scp);
1447 RDR_IoctlStatMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1455 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1459 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1461 cm_ReleaseSCache(dscp);
1467 RDR_IoctlDeleteMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1475 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1479 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1481 cm_ReleaseSCache(dscp);
1487 RDR_IoctlCheckServers(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1489 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1491 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1495 RDR_IoctlGag(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1497 /* we don't print anything superfluous, so we don't support the gag call */
1498 return CM_ERROR_INVAL;
1502 RDR_IoctlCheckVolumes(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1504 cm_SkipIoctlPath(&ioctlp->ioctl);
1506 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1509 afs_int32 RDR_IoctlSetCacheSize(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1511 cm_SkipIoctlPath(&ioctlp->ioctl);
1513 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1518 RDR_IoctlTraceControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1520 cm_SkipIoctlPath(&ioctlp->ioctl);
1522 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1526 RDR_IoctlGetCacheParms(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1528 cm_SkipIoctlPath(&ioctlp->ioctl);
1530 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1534 RDR_IoctlGetCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1536 cm_SkipIoctlPath(&ioctlp->ioctl);
1538 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1542 RDR_IoctlNewCell(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1544 cm_SkipIoctlPath(&ioctlp->ioctl);
1546 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1550 RDR_IoctlNewCell2(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1552 cm_SkipIoctlPath(&ioctlp->ioctl);
1554 return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1558 RDR_IoctlGetWsCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1560 cm_SkipIoctlPath(&ioctlp->ioctl);
1562 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1566 RDR_IoctlSysName(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1568 cm_SkipIoctlPath(&ioctlp->ioctl);
1570 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1574 RDR_IoctlGetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1576 cm_SkipIoctlPath(&ioctlp->ioctl);
1578 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1582 RDR_IoctlSetCellStatus(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1584 cm_SkipIoctlPath(&ioctlp->ioctl);
1586 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1590 RDR_IoctlSetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1592 cm_SkipIoctlPath(&ioctlp->ioctl);
1594 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1598 RDR_IoctlGetSPrefs(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1600 cm_SkipIoctlPath(&ioctlp->ioctl);
1602 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1606 RDR_IoctlStoreBehind(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1608 /* we ignore default asynchrony since we only have one way
1609 * of doing this today.
1615 RDR_IoctlCreateMountPoint(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1619 wchar_t leaf[LEAF_SIZE];
1624 code = RDR_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1628 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1630 cm_ReleaseSCache(dscp);
1635 RDR_IoctlSymlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1639 wchar_t leaf[LEAF_SIZE];
1644 code = RDR_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1645 if (code) return code;
1647 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1649 cm_ReleaseSCache(dscp);
1655 RDR_IoctlListlink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1663 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1664 if (code) return code;
1666 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1668 cm_ReleaseSCache(dscp);
1673 RDR_IoctlIslink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1674 {/*CHECK FOR VALID SYMLINK*/
1681 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1682 if (code) return code;
1684 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1686 cm_ReleaseSCache(dscp);
1692 RDR_IoctlDeletelink(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1700 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1701 if (code) return code;
1703 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1705 cm_ReleaseSCache(dscp);
1711 RDR_IoctlGetTokenIter(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1713 cm_SkipIoctlPath(&ioctlp->ioctl);
1715 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1719 RDR_IoctlGetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1721 cm_SkipIoctlPath(&ioctlp->ioctl);
1723 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1728 RDR_IoctlDelToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1730 cm_SkipIoctlPath(&ioctlp->ioctl);
1732 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1737 RDR_IoctlDelAllToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1739 cm_SkipIoctlPath(&ioctlp->ioctl);
1741 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1746 RDR_IoctlMakeSubmount(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1748 cm_SkipIoctlPath(&ioctlp->ioctl);
1750 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1754 RDR_IoctlGetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1756 cm_SkipIoctlPath(&ioctlp->ioctl);
1758 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1762 RDR_IoctlSetRxkcrypt(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1764 cm_SkipIoctlPath(&ioctlp->ioctl);
1766 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1770 RDR_IoctlRxStatProcess(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1772 cm_SkipIoctlPath(&ioctlp->ioctl);
1774 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1779 RDR_IoctlRxStatPeer(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1781 cm_SkipIoctlPath(&ioctlp->ioctl);
1783 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1787 RDR_IoctlUnicodeControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1789 cm_SkipIoctlPath(&ioctlp->ioctl);
1791 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1795 RDR_IoctlUUIDControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1797 cm_SkipIoctlPath(&ioctlp->ioctl);
1799 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1804 RDR_IoctlMemoryDump(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1806 cm_SkipIoctlPath(&ioctlp->ioctl);
1808 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1812 RDR_IoctlPathAvailability(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1817 cm_ioctlQueryOptions_t *optionsp;
1818 afs_uint32 flags = 0;
1822 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1823 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1824 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1826 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1828 cm_SkipIoctlPath(&ioctlp->ioctl);
1829 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1830 optionsp->fid.vnode, optionsp->fid.unique);
1831 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1833 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1838 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1839 cm_ReleaseSCache(scp);
1844 RDR_IoctlVolStatTest(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1850 cm_SkipIoctlPath(&ioctlp->ioctl);
1852 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
1858 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1862 RDR_IoctlSetOwner(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1867 cm_ioctlQueryOptions_t *optionsp;
1868 afs_uint32 flags = 0;
1872 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1874 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1875 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1877 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1879 cm_SkipIoctlPath(&ioctlp->ioctl);
1880 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1881 optionsp->fid.vnode, optionsp->fid.unique);
1882 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1884 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1889 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1892 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
1894 cm_ReleaseSCache(scp);
1902 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1906 RDR_IoctlSetGroup(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1911 cm_ioctlQueryOptions_t *optionsp;
1912 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, &req);
1928 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1933 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1936 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
1938 cm_ReleaseSCache(scp);
1944 RDR_IoctlGetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1949 cm_ioctlQueryOptions_t *optionsp;
1950 afs_uint32 flags = 0;
1954 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1955 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1956 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1958 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1960 cm_SkipIoctlPath(&ioctlp->ioctl);
1961 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1962 optionsp->fid.vnode, optionsp->fid.unique);
1963 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1965 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1970 code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
1972 cm_ReleaseSCache(scp);
1980 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1984 RDR_IoctlSetUnixMode(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1989 cm_ioctlQueryOptions_t *optionsp;
1990 afs_uint32 flags = 0;
1994 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1996 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1997 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1999 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2001 cm_SkipIoctlPath(&ioctlp->ioctl);
2002 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2003 optionsp->fid.vnode, optionsp->fid.unique);
2004 code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2006 code = RDR_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2011 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2014 code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2016 cm_ReleaseSCache(scp);
2022 RDR_IoctlGetVerifyData(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2024 cm_SkipIoctlPath(&ioctlp->ioctl);
2026 return cm_IoctlGetVerifyData(&ioctlp->ioctl);
2030 RDR_IoctlSetVerifyData(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2032 cm_SkipIoctlPath(&ioctlp->ioctl);
2034 return cm_IoctlSetVerifyData(&ioctlp->ioctl);