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
10 #include <afs/param.h>
28 #include "afs/afsrpc.h"
31 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
37 for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
38 smb_ioctlProcsp[i] = NULL;
40 smb_ioctlProcsp[VIOCGETAL] = smb_IoctlGetACL;
41 smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = smb_IoctlGetFileCellName;
42 smb_ioctlProcsp[VIOCSETAL] = smb_IoctlSetACL;
43 smb_ioctlProcsp[VIOC_FLUSHVOLUME] = smb_IoctlFlushVolume;
44 smb_ioctlProcsp[VIOCFLUSH] = smb_IoctlFlushFile;
45 smb_ioctlProcsp[VIOCSETVOLSTAT] = smb_IoctlSetVolumeStatus;
46 smb_ioctlProcsp[VIOCGETVOLSTAT] = smb_IoctlGetVolumeStatus;
47 smb_ioctlProcsp[VIOCWHEREIS] = smb_IoctlWhereIs;
48 smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = smb_IoctlStatMountPoint;
49 smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = smb_IoctlDeleteMountPoint;
50 smb_ioctlProcsp[VIOCCKSERV] = smb_IoctlCheckServers;
51 smb_ioctlProcsp[VIOC_GAG] = smb_IoctlGag;
52 smb_ioctlProcsp[VIOCCKBACK] = smb_IoctlCheckVolumes;
53 smb_ioctlProcsp[VIOCSETCACHESIZE] = smb_IoctlSetCacheSize;
54 smb_ioctlProcsp[VIOCGETCACHEPARMS] = smb_IoctlGetCacheParms;
55 smb_ioctlProcsp[VIOCGETCELL] = smb_IoctlGetCell;
56 smb_ioctlProcsp[VIOCNEWCELL] = smb_IoctlNewCell;
57 smb_ioctlProcsp[VIOC_GET_WS_CELL] = smb_IoctlGetWsCell;
58 smb_ioctlProcsp[VIOC_AFS_SYSNAME] = smb_IoctlSysName;
59 smb_ioctlProcsp[VIOC_GETCELLSTATUS] = smb_IoctlGetCellStatus;
60 smb_ioctlProcsp[VIOC_SETCELLSTATUS] = smb_IoctlSetCellStatus;
61 smb_ioctlProcsp[VIOC_SETSPREFS] = smb_IoctlSetSPrefs;
62 smb_ioctlProcsp[VIOC_GETSPREFS] = smb_IoctlGetSPrefs;
63 smb_ioctlProcsp[VIOC_STOREBEHIND] = smb_IoctlStoreBehind;
64 smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = smb_IoctlCreateMountPoint;
65 smb_ioctlProcsp[VIOC_TRACECTL] = smb_IoctlTraceControl;
66 smb_ioctlProcsp[VIOCSETTOK] = smb_IoctlSetToken;
67 smb_ioctlProcsp[VIOCGETTOK] = smb_IoctlGetTokenIter;
68 smb_ioctlProcsp[VIOCNEWGETTOK] = smb_IoctlGetToken;
69 smb_ioctlProcsp[VIOCDELTOK] = smb_IoctlDelToken;
70 smb_ioctlProcsp[VIOCDELALLTOK] = smb_IoctlDelAllToken;
71 smb_ioctlProcsp[VIOC_SYMLINK] = smb_IoctlSymlink;
72 smb_ioctlProcsp[VIOC_LISTSYMLINK] = smb_IoctlListlink;
73 smb_ioctlProcsp[VIOC_DELSYMLINK] = smb_IoctlDeletelink;
74 smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = smb_IoctlMakeSubmount;
75 smb_ioctlProcsp[VIOC_GETRXKCRYPT] = smb_IoctlGetRxkcrypt;
76 smb_ioctlProcsp[VIOC_SETRXKCRYPT] = smb_IoctlSetRxkcrypt;
77 smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
78 smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = smb_IoctlMemoryDump;
79 smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
80 smb_ioctlProcsp[VIOC_FLUSHALL] = smb_IoctlFlushAllVolumes;
81 smb_ioctlProcsp[VIOCGETFID] = smb_IoctlGetFid;
82 smb_ioctlProcsp[VIOCGETOWNER] = smb_IoctlGetOwner;
83 smb_ioctlProcsp[VIOC_RXSTAT_PROC] = smb_IoctlRxStatProcess;
84 smb_ioctlProcsp[VIOC_RXSTAT_PEER] = smb_IoctlRxStatPeer;
85 smb_ioctlProcsp[VIOC_UUIDCTL] = smb_IoctlUUIDControl;
86 smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = smb_IoctlPathAvailability;
87 smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
88 smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
89 smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
90 smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
91 smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
94 /* called to make a fid structure into an IOCTL fid structure */
96 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
99 cm_space_t *copyPrefix;
101 lock_ObtainMutex(&fidp->mx);
102 fidp->flags |= SMB_FID_IOCTL;
103 fidp->scp = &cm_data.fakeSCache;
104 cm_HoldSCache(fidp->scp);
105 if (fidp->ioctlp == NULL) {
106 iop = malloc(sizeof(*iop));
107 memset(iop, 0, sizeof(*iop));
112 copyPrefix = cm_GetSpace();
113 memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
114 fidp->ioctlp->prefix = copyPrefix;
116 lock_ReleaseMutex(&fidp->mx);
119 /* called when we receive a read call, does the send of the received data if
120 * this is the first read call. This is the function that actually makes the
121 * call to the ioctl code.
124 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
127 smb_ioctlProc_t *procp = NULL;
130 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
131 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
132 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAOUT;
134 /* do the call now, or fail if we didn't get an opcode, or
135 * enough of an opcode.
137 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
138 return CM_ERROR_INVAL;
139 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
140 ioctlp->ioctl.inDatap += sizeof(afs_int32);
142 osi_Log1(afsd_logp, "smb_IoctlPrepareRead opcode 0x%x", opcode);
143 /* check for opcode out of bounds */
144 if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS) {
145 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - invalid opcode");
146 return CM_ERROR_TOOBIG;
149 /* check for no such proc */
150 procp = smb_ioctlProcsp[opcode];
152 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - unassigned opcode");
153 return CM_ERROR_INVAL;
155 /* otherwise, make the call */
156 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
157 code = (*procp)(ioctlp, userp);
158 osi_Log1(afsd_logp, "smb_IoctlPrepareRead operation returns code 0x%x", code);
160 /* copy in return code */
161 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
162 } else if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAOUT)) {
163 osi_Log0(afsd_logp, "Ioctl invalid state - dataout expected");
164 return CM_ERROR_INVAL;
170 /* called when we receive a write call. If this is the first write call after
171 * a series of reads (or the very first call), then we start a new call.
172 * We also ensure that things are properly initialized for the start of a call.
175 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
177 /* make sure the buffer(s) are allocated */
178 if (!ioctlp->ioctl.inAllocp)
179 ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
180 if (!ioctlp->ioctl.outAllocp)
181 ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
183 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
184 (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
185 (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
187 /* and make sure that we've reset our state for the new incoming request */
188 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
189 ioctlp->ioctl.inCopied = 0;
190 ioctlp->ioctl.outCopied = 0;
191 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
192 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
193 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
194 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAOUT;
198 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
200 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
204 afs_int32 leftToCopy;
210 count = smb_GetSMBParm(inp, 1);
211 userp = smb_GetUserFromVCP(vcp, inp);
214 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
216 cm_ReleaseUser(userp);
217 return CM_ERROR_NOSUCHPATH;
220 /* turn the connection around, if required */
221 code = smb_IoctlPrepareRead(fidp, iop, userp);
224 cm_ReleaseUser(userp);
228 leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
229 if (leftToCopy < 0) {
230 osi_Log0(afsd_logp, "smb_IoctlRead leftToCopy went negative");
231 cm_ReleaseUser(userp);
232 return CM_ERROR_INVAL;
234 if (count > leftToCopy)
237 /* now set the parms for a read of count bytes */
238 smb_SetSMBParm(outp, 0, count);
239 smb_SetSMBParm(outp, 1, 0);
240 smb_SetSMBParm(outp, 2, 0);
241 smb_SetSMBParm(outp, 3, 0);
242 smb_SetSMBParm(outp, 4, 0);
244 smb_SetSMBDataLength(outp, count+3);
246 op = smb_GetSMBData(outp, NULL);
248 *op++ = (char)(count & 0xff);
249 *op++ = (char)((count >> 8) & 0xff);
251 /* now copy the data into the response packet */
252 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
254 /* and adjust the counters */
255 iop->ioctl.outCopied += count;
257 cm_ReleaseUser(userp);
262 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
266 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
272 int inDataBlockCount;
275 count = smb_GetSMBParm(inp, 1);
278 smb_IoctlPrepareWrite(fidp, iop);
280 op = smb_GetSMBData(inp, NULL);
281 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
283 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
284 code = CM_ERROR_TOOBIG;
289 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
292 iop->ioctl.inCopied += count;
295 /* return # of bytes written */
297 smb_SetSMBParm(outp, 0, count);
298 smb_SetSMBDataLength(outp, 0);
304 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
308 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
314 int inDataBlockCount;
317 count = smb_GetSMBParm(inp, 10);
320 smb_IoctlPrepareWrite(fidp, iop);
322 op = inp->data + smb_GetSMBParm(inp, 11);
323 inDataBlockCount = count;
325 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
326 code = CM_ERROR_TOOBIG;
331 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
334 iop->ioctl.inCopied += count;
337 /* return # of bytes written */
339 smb_SetSMBParm(outp, 2, count);
340 smb_SetSMBParm(outp, 3, 0); /* reserved */
341 smb_SetSMBParm(outp, 4, 0); /* reserved */
342 smb_SetSMBParm(outp, 5, 0); /* reserved */
343 smb_SetSMBDataLength(outp, 0);
350 /* called from V3 read to handle IOCTL descriptor reads */
352 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
355 unsigned short count;
363 count = smb_GetSMBParm(inp, 5);
365 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
367 return CM_ERROR_BADSMB;
368 userp = smb_GetUserFromUID(uidp);
369 osi_assertx(userp != NULL, "null cm_user_t");
371 if (uidp && uidp->unp) {
372 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %S",
374 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
377 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
378 uidp->userID, userp);
380 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
384 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
387 smb_ReleaseUID(uidp);
388 cm_ReleaseUser(userp);
389 return CM_ERROR_NOSUCHPATH;
392 code = smb_IoctlPrepareRead(fidp, iop, userp);
395 smb_ReleaseUID(uidp);
398 cm_ReleaseUser(userp);
402 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
403 if (leftToCopy < 0) {
404 osi_Log0(afsd_logp, "smb_IoctlV3Read leftToCopy went negative");
405 cm_ReleaseUser(userp);
406 return CM_ERROR_INVAL;
408 if (count > leftToCopy)
409 count = (unsigned short)leftToCopy;
411 /* 0 and 1 are reserved for request chaining, were setup by our caller,
412 * and will be further filled in after we return.
414 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
415 smb_SetSMBParm(outp, 3, 0); /* resvd */
416 smb_SetSMBParm(outp, 4, 0); /* resvd */
417 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
418 /* fill in #6 when we have all the parameters' space reserved */
419 smb_SetSMBParm(outp, 7, 0); /* resv'd */
420 smb_SetSMBParm(outp, 8, 0); /* resv'd */
421 smb_SetSMBParm(outp, 9, 0); /* resv'd */
422 smb_SetSMBParm(outp, 10, 0); /* resv'd */
423 smb_SetSMBParm(outp, 11, 0); /* reserved */
425 /* get op ptr after putting in the last parm, since otherwise we don't
426 * know where the data really is.
428 op = smb_GetSMBData(outp, NULL);
430 /* now fill in offset from start of SMB header to first data byte (to op) */
431 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
433 /* set the packet data length the count of the # of bytes */
434 smb_SetSMBDataLength(outp, count);
436 /* now copy the data into the response packet */
437 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
439 /* and adjust the counters */
440 iop->ioctl.outCopied += count;
442 /* and cleanup things */
443 cm_ReleaseUser(userp);
448 /* called from Read Raw to handle IOCTL descriptor reads */
450 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
462 userp = smb_GetUserFromVCP(vcp, inp);
465 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
466 if (uidp && uidp->unp) {
467 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
469 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
471 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
472 uidp->userID, userp);
474 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
478 smb_ReleaseUID(uidp);
480 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
482 code = CM_ERROR_NOSUCHPATH;
486 code = smb_IoctlPrepareRead(fidp, iop, userp);
491 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
492 if (leftToCopy < 0) {
493 osi_Log0(afsd_logp, "smb_IoctlReadRaw leftToCopy went negative");
494 code = CM_ERROR_INVAL;
499 memset((char *)ncbp, 0, sizeof(NCB));
501 ncbp->ncb_length = (unsigned short) leftToCopy;
502 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
503 ncbp->ncb_command = NCBSEND;
504 /*ncbp->ncb_lana_num = smb_LANadapter;*/
505 ncbp->ncb_lana_num = vcp->lana;
507 ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
508 code = Netbios(ncbp);
511 osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
514 cm_ReleaseUser(userp);
519 /* parse the passed-in file name and do a namei on it. If we fail,
520 * return an error code, otherwise return the vnode located in *scpp.
522 #define CM_PARSE_FLAG_LITERAL 1
525 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
526 cm_scache_t **scpp, afs_uint32 flags)
529 cm_scache_t *substRootp = NULL;
530 cm_scache_t *iscp = NULL;
532 clientchar_t *relativePath = NULL;
533 clientchar_t *lastComponent = NULL;
534 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
536 inPath = ioctlp->ioctl.inDatap;
537 /* setup the next data value for the caller to use */
538 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
540 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
542 /* This is usually the file name, but for StatMountPoint it is the path. */
543 /* ioctlp->ioctl.inDatap can be either of the form:
546 * \\netbios-name\submount\path\.
547 * \\netbios-name\submount\path\file
550 /* We do not perform path name translation on the ioctl path data
551 * because these paths were not translated by Windows through the
552 * file system API. Therefore, they are not OEM characters but
553 * whatever the display character set is.
556 // TranslateExtendedChars(relativePath);
558 /* This is usually nothing, but for StatMountPoint it is the file name. */
559 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
561 /* If the string starts with our UTF-8 prefix (which is the
562 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
563 strings), we assume that the provided path is UTF-8. Otherwise
564 we have to convert the string to UTF-8, since that is what we
565 want to use everywhere else.*/
567 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
568 /* String is UTF-8 */
569 inPath += utf8_prefix_size;
570 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
572 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
576 /* Not a UTF-8 string */
577 /* TODO: If this is an OEM string, we should convert it to
579 if (smb_StoreAnsiFilenames) {
580 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
584 relativePath = malloc(cch * sizeof(clientchar_t));
585 cm_AnsiToClientString(inPath, -1, relativePath, cch);
587 TranslateExtendedChars(inPath);
589 cch = cm_OemToClientString(inPath, -1, NULL, 0);
593 relativePath = malloc(cch * sizeof(clientchar_t));
594 cm_OemToClientString(inPath, -1, relativePath, cch);
598 if (relativePath[0] == relativePath[1] &&
599 relativePath[1] == '\\' &&
600 !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
601 cm_ClientStrLen(cm_NetbiosNameC)))
603 clientchar_t shareName[256];
604 clientchar_t *sharePath;
607 /* We may have found a UNC path.
608 * If the first component is the NetbiosName,
609 * then throw out the second component (the submount)
610 * since it had better expand into the value of ioctl->tidPathp
613 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1; /* buffer overflow vuln.? */
614 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
617 for (i = 0; *p && *p != '\\'; i++,p++ ) {
620 p++; /* skip past trailing slash */
621 shareName[i] = 0; /* terminate string */
623 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
625 /* we found a sharename, therefore use the resulting path */
626 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
627 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
628 userp, sharePath, reqp, &substRootp);
631 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
637 lastComponent = cm_ClientStrRChr(p, '\\');
638 if (lastComponent && (lastComponent - p) > 1 &&
639 cm_ClientStrLen(lastComponent) > 1) {
640 *lastComponent = '\0';
643 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
644 userp, NULL, reqp, &iscp);
646 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
647 userp, NULL, reqp, scpp);
649 cm_ReleaseSCache(iscp);
651 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
652 userp, NULL, reqp, scpp);
654 cm_ReleaseSCache(substRootp);
656 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
662 /* otherwise, treat the name as a cellname mounted off the afs root.
663 * This requires that we reconstruct the shareName string with
664 * leading and trailing slashes.
666 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
667 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
671 for (i = 1; *p && *p != '\\'; i++,p++ ) {
674 p++; /* skip past trailing slash */
675 shareName[i++] = '/'; /* add trailing slash */
676 shareName[i] = 0; /* terminate string */
679 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
680 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
681 userp, shareName, reqp, &substRootp);
683 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
689 lastComponent = cm_ClientStrRChr(p, '\\');
690 if (lastComponent && (lastComponent - p) > 1 &&
691 cm_ClientStrLen(lastComponent) > 1) {
692 *lastComponent = '\0';
695 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
696 userp, NULL, reqp, &iscp);
698 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
699 userp, NULL, reqp, scpp);
701 cm_ReleaseSCache(iscp);
703 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
704 userp, NULL, reqp, scpp);
708 cm_ReleaseSCache(substRootp);
709 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
716 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
717 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
718 userp, ioctlp->tidPathp, reqp, &substRootp);
720 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
726 lastComponent = cm_ClientStrRChr(relativePath, '\\');
727 if (lastComponent && (lastComponent - relativePath) > 1 &&
728 cm_ClientStrLen(lastComponent) > 1) {
729 *lastComponent = '\0';
732 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
733 userp, NULL, reqp, &iscp);
735 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
736 userp, NULL, reqp, scpp);
738 cm_ReleaseSCache(iscp);
740 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
741 userp, NULL, reqp, scpp);
744 cm_ReleaseSCache(substRootp);
745 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
753 cm_ReleaseSCache(substRootp);
755 /* and return success */
756 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
765 #define LEAF_SIZE 256
766 /* parse the passed-in file name and do a namei on its parent. If we fail,
767 * return an error code, otherwise return the vnode located in *scpp.
770 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
771 cm_scache_t **scpp, clientchar_t *leafp)
774 clientchar_t tbuffer[1024];
775 clientchar_t *tp, *jp;
776 cm_scache_t *substRootp = NULL;
777 clientchar_t *inpathp = NULL;
780 inpathdatap = ioctlp->ioctl.inDatap;
782 /* If the string starts with our UTF-8 prefix (which is the
783 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
784 strings), we assume that the provided path is UTF-8. Otherwise
785 we have to convert the string to UTF-8, since that is what we
786 want to use everywhere else.*/
788 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
790 /* String is UTF-8 */
791 inpathdatap += utf8_prefix_size;
792 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
794 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
798 /* Not a UTF-8 string */
799 /* TODO: If this is an OEM string, we should convert it to
801 if (smb_StoreAnsiFilenames) {
802 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
806 inpathp = malloc(cch * sizeof(clientchar_t));
807 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
809 TranslateExtendedChars(inpathdatap);
811 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
815 inpathp = malloc(cch * sizeof(clientchar_t));
816 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
820 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
821 tp = cm_ClientStrRChr(tbuffer, '\\');
822 jp = cm_ClientStrRChr(tbuffer, '/');
825 else if (jp && (tp - tbuffer) < (jp - tbuffer))
828 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
830 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
835 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
839 inpathp = NULL; /* We don't need this from this point on */
841 if (tbuffer[0] == tbuffer[1] &&
842 tbuffer[1] == '\\' &&
843 !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
844 cm_ClientStrLen(cm_NetbiosNameC)))
846 clientchar_t shareName[256];
847 clientchar_t *sharePath;
850 /* We may have found a UNC path.
851 * If the first component is the NetbiosName,
852 * then throw out the second component (the submount)
853 * since it had better expand into the value of ioctl->tidPathp
856 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
857 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
860 for (i = 0; *p && *p != '\\'; i++,p++ ) {
863 p++; /* skip past trailing slash */
864 shareName[i] = 0; /* terminate string */
866 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
868 /* we found a sharename, therefore use the resulting path */
869 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
870 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
871 userp, sharePath, reqp, &substRootp);
873 if (code) return code;
875 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
876 userp, NULL, reqp, scpp);
877 cm_ReleaseSCache(substRootp);
878 if (code) return code;
880 /* otherwise, treat the name as a cellname mounted off the afs root.
881 * This requires that we reconstruct the shareName string with
882 * leading and trailing slashes.
884 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
885 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
889 for (i = 1; *p && *p != '\\'; i++,p++ ) {
892 p++; /* skip past trailing slash */
893 shareName[i++] = '/'; /* add trailing slash */
894 shareName[i] = 0; /* terminate string */
896 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
897 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
898 userp, shareName, reqp, &substRootp);
899 if (code) return code;
901 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
902 userp, NULL, reqp, scpp);
903 cm_ReleaseSCache(substRootp);
904 if (code) return code;
907 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
908 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
909 userp, ioctlp->tidPathp, reqp, &substRootp);
910 if (code) return code;
912 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
913 userp, NULL, reqp, scpp);
914 cm_ReleaseSCache(substRootp);
915 if (code) return code;
918 /* # of bytes of path */
919 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
920 ioctlp->ioctl.inDatap += code;
922 /* and return success */
927 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
934 struct ClearToken ct;
940 int release_userp = 0;
941 clientchar_t *uname = NULL;
942 clientchar_t *smbname = NULL;
943 clientchar_t *wdir = NULL;
946 saveDataPtr = ioctlp->ioctl.inDatap;
948 cm_SkipIoctlPath(&ioctlp->ioctl);
950 tp = ioctlp->ioctl.inDatap;
953 memcpy(&ticketLen, tp, sizeof(ticketLen));
954 tp += sizeof(ticketLen);
955 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
956 return CM_ERROR_INVAL;
958 /* remember ticket and skip over it for now */
962 /* clear token size */
963 memcpy(&ctSize, tp, sizeof(ctSize));
964 tp += sizeof(ctSize);
965 if (ctSize != sizeof(struct ClearToken))
966 return CM_ERROR_INVAL;
969 memcpy(&ct, tp, ctSize);
971 if (ct.AuthHandle == -1)
972 ct.AuthHandle = 999; /* more rxvab compat stuff */
974 /* more stuff, if any */
975 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
976 /* flags: logon flag */
977 memcpy(&flags, tp, sizeof(int));
982 fschar_t * cellnamep;
985 temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
986 cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
987 cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
993 code = CM_ERROR_NOSUCHCELL;
996 tp += strlen(tp) + 1;
999 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1000 tp += strlen(tp) + 1;
1002 if (flags & PIOCTL_LOGON) {
1003 /* SMB user name with which to associate tokens */
1004 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1005 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
1006 osi_LogSaveClientString(smb_logp,uname),
1007 osi_LogSaveClientString(smb_logp,smbname));
1008 fprintf(stderr, "SMB name = %S\n", smbname);
1009 tp += strlen(tp) + 1;
1011 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%S]",
1012 osi_LogSaveClientString(smb_logp, uname));
1016 memcpy(&uuid, tp, sizeof(uuid));
1017 if (!cm_FindTokenEvent(uuid, sessionKey)) {
1018 code = CM_ERROR_INVAL;
1022 cellp = cm_data.rootCellp;
1023 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1026 if (flags & PIOCTL_LOGON) {
1027 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
1028 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1032 /* store the token */
1033 lock_ObtainMutex(&userp->mx);
1034 ucellp = cm_GetUCell(userp, cellp);
1035 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1036 ucellp->ticketLen = ticketLen;
1037 if (ucellp->ticketp)
1038 free(ucellp->ticketp); /* Discard old token if any */
1039 ucellp->ticketp = malloc(ticketLen);
1040 memcpy(ucellp->ticketp, ticket, ticketLen);
1042 * Get the session key from the RPC, rather than from the pioctl.
1045 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1047 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1048 ucellp->kvno = ct.AuthHandle;
1049 ucellp->expirationTime = ct.EndTimestamp;
1052 ucellp->uid = ANONYMOUSID;
1055 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1057 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1060 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1061 lock_ReleaseMutex(&userp->mx);
1063 if (flags & PIOCTL_LOGON) {
1064 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1067 cm_ResetACLCache(cellp, userp);
1071 cm_ReleaseUser(userp);
1085 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
1087 smb_user_t *uidp = ioctlp->uidp;
1089 if (uidp && uidp->unp) {
1092 cch = cm_ClientStringToUtf8(uidp->unp->name,
1094 ioctlp->ioctl.outDatap,
1095 (SMB_IOCTL_MAXDATA -
1096 (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1097 / sizeof(cm_utf8char_t));
1099 ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1106 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1111 cm_ioctlQueryOptions_t *optionsp;
1112 afs_uint32 flags = 0;
1116 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1117 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1118 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1120 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1122 cm_SkipIoctlPath(&ioctlp->ioctl);
1123 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1124 optionsp->fid.vnode, optionsp->fid.unique);
1125 code = cm_GetSCache(&fid, &scp, userp, &req);
1127 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1133 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1135 cm_ReleaseSCache(scp);
1140 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1145 afs_uint32 flags = 0;
1149 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1153 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1155 cm_ReleaseSCache(scp);
1160 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1165 cm_ioctlQueryOptions_t *optionsp;
1166 afs_uint32 flags = 0;
1170 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1171 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1172 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1174 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1176 cm_SkipIoctlPath(&ioctlp->ioctl);
1177 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1178 optionsp->fid.vnode, optionsp->fid.unique);
1179 code = cm_GetSCache(&fid, &scp, userp, &req);
1181 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1186 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1188 cm_ReleaseSCache(scp);
1194 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1200 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1202 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1206 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
1211 cm_ioctlQueryOptions_t *optionsp;
1212 afs_uint32 flags = 0;
1216 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1217 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1218 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1220 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1222 cm_SkipIoctlPath(&ioctlp->ioctl);
1223 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1224 optionsp->fid.vnode, optionsp->fid.unique);
1225 code = cm_GetSCache(&fid, &scp, userp, &req);
1227 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1232 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1234 cm_ReleaseSCache(scp);
1240 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
1245 cm_ioctlQueryOptions_t *optionsp;
1246 afs_uint32 flags = 0;
1250 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1251 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1252 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1254 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1256 cm_SkipIoctlPath(&ioctlp->ioctl);
1257 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1258 optionsp->fid.vnode, optionsp->fid.unique);
1259 code = cm_GetSCache(&fid, &scp, userp, &req);
1261 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1266 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1268 cm_ReleaseSCache(scp);
1273 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1281 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1282 if (code) return code;
1284 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1285 cm_ReleaseSCache(scp);
1291 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1295 cm_ioctlQueryOptions_t *optionsp;
1296 afs_uint32 flags = 0;
1301 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1302 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1303 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1305 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1307 cm_SkipIoctlPath(&ioctlp->ioctl);
1308 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1309 optionsp->fid.vnode, optionsp->fid.unique);
1310 code = cm_GetSCache(&fid, &scp, userp, &req);
1312 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1317 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1319 cm_ReleaseSCache(scp);
1325 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
1330 cm_ioctlQueryOptions_t * optionsp;
1331 afs_uint32 flags = 0;
1335 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1336 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1337 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1339 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1343 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1345 cm_ReleaseSCache(scp);
1351 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp)
1356 cm_ioctlQueryOptions_t * optionsp;
1357 afs_uint32 flags = 0;
1361 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1362 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1363 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1365 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1367 cm_SkipIoctlPath(&ioctlp->ioctl);
1368 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1369 optionsp->fid.vnode, optionsp->fid.unique);
1370 code = cm_GetSCache(&fid, &scp, userp, &req);
1372 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1377 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1379 cm_ReleaseSCache(scp);
1385 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1390 cm_ioctlQueryOptions_t *optionsp;
1391 afs_uint32 flags = 0;
1395 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1396 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1397 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1399 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1401 cm_SkipIoctlPath(&ioctlp->ioctl);
1402 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1403 optionsp->fid.vnode, optionsp->fid.unique);
1404 code = cm_GetSCache(&fid, &scp, userp, &req);
1406 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1411 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1413 cm_ReleaseSCache(scp);
1419 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1424 cm_ioctlQueryOptions_t *optionsp;
1425 afs_uint32 flags = 0;
1429 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1430 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1431 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1433 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1435 cm_SkipIoctlPath(&ioctlp->ioctl);
1436 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1437 optionsp->fid.vnode, optionsp->fid.unique);
1438 code = cm_GetSCache(&fid, &scp, userp, &req);
1440 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1445 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1447 cm_ReleaseSCache(scp);
1454 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1462 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1466 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1468 cm_ReleaseSCache(dscp);
1474 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1482 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1486 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1488 cm_ReleaseSCache(dscp);
1494 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1496 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1498 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1502 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1504 /* we don't print anything superfluous, so we don't support the gag call */
1505 return CM_ERROR_INVAL;
1509 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1511 cm_SkipIoctlPath(&ioctlp->ioctl);
1513 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1516 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1518 cm_SkipIoctlPath(&ioctlp->ioctl);
1520 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1525 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1527 cm_SkipIoctlPath(&ioctlp->ioctl);
1529 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1533 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1535 cm_SkipIoctlPath(&ioctlp->ioctl);
1537 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1541 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1543 cm_SkipIoctlPath(&ioctlp->ioctl);
1545 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1549 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1551 cm_SkipIoctlPath(&ioctlp->ioctl);
1553 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1557 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1559 cm_SkipIoctlPath(&ioctlp->ioctl);
1561 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1565 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1567 cm_SkipIoctlPath(&ioctlp->ioctl);
1569 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1573 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1575 cm_SkipIoctlPath(&ioctlp->ioctl);
1577 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1581 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1583 cm_SkipIoctlPath(&ioctlp->ioctl);
1585 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1589 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1591 cm_SkipIoctlPath(&ioctlp->ioctl);
1593 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1597 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1599 cm_SkipIoctlPath(&ioctlp->ioctl);
1601 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1605 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1607 /* we ignore default asynchrony since we only have one way
1608 * of doing this today.
1614 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1618 clientchar_t leaf[LEAF_SIZE];
1623 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1627 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1629 cm_ReleaseSCache(dscp);
1634 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1638 clientchar_t leaf[LEAF_SIZE];
1643 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1644 if (code) return code;
1646 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1648 cm_ReleaseSCache(dscp);
1654 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1662 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1663 if (code) return code;
1665 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1667 cm_ReleaseSCache(dscp);
1672 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1673 {/*CHECK FOR VALID SYMLINK*/
1680 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1681 if (code) return code;
1683 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1685 cm_ReleaseSCache(dscp);
1691 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1699 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1700 if (code) return code;
1702 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1704 cm_ReleaseSCache(dscp);
1710 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
1712 cm_SkipIoctlPath(&ioctlp->ioctl);
1714 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1718 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1720 cm_SkipIoctlPath(&ioctlp->ioctl);
1722 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1727 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1729 cm_SkipIoctlPath(&ioctlp->ioctl);
1731 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1736 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1738 cm_SkipIoctlPath(&ioctlp->ioctl);
1740 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1745 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp)
1747 cm_SkipIoctlPath(&ioctlp->ioctl);
1749 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1753 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1755 cm_SkipIoctlPath(&ioctlp->ioctl);
1757 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1761 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1763 cm_SkipIoctlPath(&ioctlp->ioctl);
1765 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1769 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
1771 cm_SkipIoctlPath(&ioctlp->ioctl);
1773 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1778 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
1780 cm_SkipIoctlPath(&ioctlp->ioctl);
1782 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1786 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1788 cm_SkipIoctlPath(&ioctlp->ioctl);
1790 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1794 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1796 cm_SkipIoctlPath(&ioctlp->ioctl);
1798 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1803 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
1805 cm_SkipIoctlPath(&ioctlp->ioctl);
1807 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1811 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
1816 cm_ioctlQueryOptions_t *optionsp;
1817 afs_uint32 flags = 0;
1821 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1822 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1823 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1825 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1827 cm_SkipIoctlPath(&ioctlp->ioctl);
1828 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1829 optionsp->fid.vnode, optionsp->fid.unique);
1830 code = cm_GetSCache(&fid, &scp, userp, &req);
1832 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1837 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1838 cm_ReleaseSCache(scp);
1843 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
1849 cm_SkipIoctlPath(&ioctlp->ioctl);
1851 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
1857 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1861 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1866 cm_ioctlQueryOptions_t *optionsp;
1867 afs_uint32 flags = 0;
1871 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1873 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1874 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1876 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1878 cm_SkipIoctlPath(&ioctlp->ioctl);
1879 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1880 optionsp->fid.vnode, optionsp->fid.unique);
1881 code = cm_GetSCache(&fid, &scp, userp, &req);
1883 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1888 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1891 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
1893 cm_ReleaseSCache(scp);
1901 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1905 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp)
1910 cm_ioctlQueryOptions_t *optionsp;
1911 afs_uint32 flags = 0;
1915 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1917 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1918 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1920 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1922 cm_SkipIoctlPath(&ioctlp->ioctl);
1923 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1924 optionsp->fid.vnode, optionsp->fid.unique);
1925 code = cm_GetSCache(&fid, &scp, userp, &req);
1927 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1932 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1935 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
1937 cm_ReleaseSCache(scp);