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;
92 /* called to make a fid structure into an IOCTL fid structure */
94 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
97 cm_space_t *copyPrefix;
99 lock_ObtainMutex(&fidp->mx);
100 fidp->flags |= SMB_FID_IOCTL;
101 fidp->scp = &cm_data.fakeSCache;
102 cm_HoldSCache(fidp->scp);
103 if (fidp->ioctlp == NULL) {
104 iop = malloc(sizeof(*iop));
105 memset(iop, 0, sizeof(*iop));
110 copyPrefix = cm_GetSpace();
111 memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
112 fidp->ioctlp->prefix = copyPrefix;
114 lock_ReleaseMutex(&fidp->mx);
117 /* called when we receive a read call, does the send of the received data if
118 * this is the first read call. This is the function that actually makes the
119 * call to the ioctl code.
122 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
125 smb_ioctlProc_t *procp = NULL;
128 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
129 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
131 /* do the call now, or fail if we didn't get an opcode, or
132 * enough of an opcode.
134 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
135 return CM_ERROR_INVAL;
136 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
137 ioctlp->ioctl.inDatap += sizeof(afs_int32);
139 osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode);
141 /* check for opcode out of bounds */
142 if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS)
143 return CM_ERROR_TOOBIG;
145 /* check for no such proc */
146 procp = smb_ioctlProcsp[opcode];
148 return CM_ERROR_BADOP;
150 /* otherwise, make the call */
151 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
152 code = (*procp)(ioctlp, userp);
154 osi_Log1(afsd_logp, "Ioctl return code 0x%x", code);
156 /* copy in return code */
157 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
162 /* called when we receive a write call. If this is the first write call after
163 * a series of reads (or the very first call), then we start a new call.
164 * We also ensure that things are properly initialized for the start of a call.
167 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
169 /* make sure the buffer(s) are allocated */
170 if (!ioctlp->ioctl.inAllocp)
171 ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
172 if (!ioctlp->ioctl.outAllocp)
173 ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
175 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
176 (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
177 (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
179 /* and make sure that we've reset our state for the new incoming request */
180 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
181 ioctlp->ioctl.inCopied = 0;
182 ioctlp->ioctl.outCopied = 0;
183 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
184 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
185 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
189 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
191 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
195 afs_int32 leftToCopy;
201 count = smb_GetSMBParm(inp, 1);
202 userp = smb_GetUserFromVCP(vcp, inp);
205 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
207 cm_ReleaseUser(userp);
208 return CM_ERROR_NOSUCHPATH;
211 /* turn the connection around, if required */
212 code = smb_IoctlPrepareRead(fidp, iop, userp);
215 cm_ReleaseUser(userp);
219 leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
220 if (count > leftToCopy)
223 /* now set the parms for a read of count bytes */
224 smb_SetSMBParm(outp, 0, count);
225 smb_SetSMBParm(outp, 1, 0);
226 smb_SetSMBParm(outp, 2, 0);
227 smb_SetSMBParm(outp, 3, 0);
228 smb_SetSMBParm(outp, 4, 0);
230 smb_SetSMBDataLength(outp, count+3);
232 op = smb_GetSMBData(outp, NULL);
234 *op++ = (char)(count & 0xff);
235 *op++ = (char)((count >> 8) & 0xff);
237 /* now copy the data into the response packet */
238 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
240 /* and adjust the counters */
241 iop->ioctl.outCopied += count;
243 cm_ReleaseUser(userp);
248 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
252 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
258 int inDataBlockCount;
261 count = smb_GetSMBParm(inp, 1);
264 smb_IoctlPrepareWrite(fidp, iop);
266 op = smb_GetSMBData(inp, NULL);
267 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
269 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
270 code = CM_ERROR_TOOBIG;
275 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
278 iop->ioctl.inCopied += count;
281 /* return # of bytes written */
283 smb_SetSMBParm(outp, 0, count);
284 smb_SetSMBDataLength(outp, 0);
290 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
294 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
300 int inDataBlockCount;
303 count = smb_GetSMBParm(inp, 10);
306 smb_IoctlPrepareWrite(fidp, iop);
308 op = inp->data + smb_GetSMBParm(inp, 11);
309 inDataBlockCount = count;
311 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
312 code = CM_ERROR_TOOBIG;
317 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
320 iop->ioctl.inCopied += count;
323 /* return # of bytes written */
325 smb_SetSMBParm(outp, 2, count);
326 smb_SetSMBParm(outp, 3, 0); /* reserved */
327 smb_SetSMBParm(outp, 4, 0); /* reserved */
328 smb_SetSMBParm(outp, 5, 0); /* reserved */
329 smb_SetSMBDataLength(outp, 0);
336 /* called from V3 read to handle IOCTL descriptor reads */
338 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
349 count = smb_GetSMBParm(inp, 5);
351 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
352 userp = smb_GetUserFromUID(uidp);
353 osi_assertx(userp != NULL, "null cm_user_t");
355 if (uidp && uidp->unp) {
356 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %S",
358 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
361 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
362 uidp->userID, userp);
364 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
368 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
371 smb_ReleaseUID(uidp);
372 cm_ReleaseUser(userp);
373 return CM_ERROR_NOSUCHPATH;
376 code = smb_IoctlPrepareRead(fidp, iop, userp);
379 smb_ReleaseUID(uidp);
382 cm_ReleaseUser(userp);
386 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
387 if (count > leftToCopy)
390 /* 0 and 1 are reserved for request chaining, were setup by our caller,
391 * and will be further filled in after we return.
393 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
394 smb_SetSMBParm(outp, 3, 0); /* resvd */
395 smb_SetSMBParm(outp, 4, 0); /* resvd */
396 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
397 /* fill in #6 when we have all the parameters' space reserved */
398 smb_SetSMBParm(outp, 7, 0); /* resv'd */
399 smb_SetSMBParm(outp, 8, 0); /* resv'd */
400 smb_SetSMBParm(outp, 9, 0); /* resv'd */
401 smb_SetSMBParm(outp, 10, 0); /* resv'd */
402 smb_SetSMBParm(outp, 11, 0); /* reserved */
404 /* get op ptr after putting in the last parm, since otherwise we don't
405 * know where the data really is.
407 op = smb_GetSMBData(outp, NULL);
409 /* now fill in offset from start of SMB header to first data byte (to op) */
410 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
412 /* set the packet data length the count of the # of bytes */
413 smb_SetSMBDataLength(outp, count);
415 /* now copy the data into the response packet */
416 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
418 /* and adjust the counters */
419 iop->ioctl.outCopied += count;
421 /* and cleanup things */
422 cm_ReleaseUser(userp);
427 /* called from Read Raw to handle IOCTL descriptor reads */
429 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
441 userp = smb_GetUserFromVCP(vcp, inp);
444 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
445 if (uidp && uidp->unp) {
446 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
448 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
450 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
451 uidp->userID, userp);
453 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
457 smb_ReleaseUID(uidp);
459 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
461 code = CM_ERROR_NOSUCHPATH;
465 code = smb_IoctlPrepareRead(fidp, iop, userp);
470 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
473 memset((char *)ncbp, 0, sizeof(NCB));
475 ncbp->ncb_length = (unsigned short) leftToCopy;
476 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
477 ncbp->ncb_command = NCBSEND;
478 /*ncbp->ncb_lana_num = smb_LANadapter;*/
479 ncbp->ncb_lana_num = vcp->lana;
481 ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
482 code = Netbios(ncbp);
485 osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
488 cm_ReleaseUser(userp);
493 /* parse the passed-in file name and do a namei on it. If we fail,
494 * return an error code, otherwise return the vnode located in *scpp.
496 #define CM_PARSE_FLAG_LITERAL 1
499 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
500 cm_scache_t **scpp, afs_uint32 flags)
503 cm_scache_t *substRootp = NULL;
504 cm_scache_t *iscp = NULL;
506 clientchar_t *relativePath = NULL;
507 clientchar_t *lastComponent = NULL;
508 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
510 inPath = ioctlp->ioctl.inDatap;
511 /* setup the next data value for the caller to use */
512 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
514 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
516 /* This is usually the file name, but for StatMountPoint it is the path. */
517 /* ioctlp->ioctl.inDatap can be either of the form:
520 * \\netbios-name\submount\path\.
521 * \\netbios-name\submount\path\file
524 /* We do not perform path name translation on the ioctl path data
525 * because these paths were not translated by Windows through the
526 * file system API. Therefore, they are not OEM characters but
527 * whatever the display character set is.
530 // TranslateExtendedChars(relativePath);
532 /* This is usually nothing, but for StatMountPoint it is the file name. */
533 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
535 /* If the string starts with our UTF-8 prefix (which is the
536 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
537 strings), we assume that the provided path is UTF-8. Otherwise
538 we have to convert the string to UTF-8, since that is what we
539 want to use everywhere else.*/
541 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
542 /* String is UTF-8 */
543 inPath += utf8_prefix_size;
544 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
546 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
550 /* Not a UTF-8 string */
551 /* TODO: If this is an OEM string, we should convert it to
553 if (smb_StoreAnsiFilenames) {
554 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
558 relativePath = malloc(cch * sizeof(clientchar_t));
559 cm_AnsiToClientString(inPath, -1, relativePath, cch);
561 TranslateExtendedChars(inPath);
563 cch = cm_OemToClientString(inPath, -1, NULL, 0);
567 relativePath = malloc(cch * sizeof(clientchar_t));
568 cm_OemToClientString(inPath, -1, relativePath, cch);
572 if (relativePath[0] == relativePath[1] &&
573 relativePath[1] == '\\' &&
574 !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
575 cm_ClientStrLen(cm_NetbiosNameC)))
577 clientchar_t shareName[256];
578 clientchar_t *sharePath;
581 /* We may have found a UNC path.
582 * If the first component is the NetbiosName,
583 * then throw out the second component (the submount)
584 * since it had better expand into the value of ioctl->tidPathp
587 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1; /* buffer overflow vuln.? */
588 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
591 for (i = 0; *p && *p != '\\'; i++,p++ ) {
594 p++; /* skip past trailing slash */
595 shareName[i] = 0; /* terminate string */
597 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
599 /* we found a sharename, therefore use the resulting path */
600 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
601 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
602 userp, sharePath, reqp, &substRootp);
605 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
611 lastComponent = cm_ClientStrRChr(p, '\\');
612 if (lastComponent && (lastComponent - p) > 1 &&
613 cm_ClientStrLen(lastComponent) > 1) {
614 *lastComponent = '\0';
617 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
618 userp, NULL, reqp, &iscp);
620 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
621 userp, NULL, reqp, scpp);
623 cm_ReleaseSCache(iscp);
625 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
626 userp, NULL, reqp, scpp);
628 cm_ReleaseSCache(substRootp);
630 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
636 /* otherwise, treat the name as a cellname mounted off the afs root.
637 * This requires that we reconstruct the shareName string with
638 * leading and trailing slashes.
640 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
641 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
645 for (i = 1; *p && *p != '\\'; i++,p++ ) {
648 p++; /* skip past trailing slash */
649 shareName[i++] = '/'; /* add trailing slash */
650 shareName[i] = 0; /* terminate string */
653 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
654 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
655 userp, shareName, reqp, &substRootp);
657 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
663 lastComponent = cm_ClientStrRChr(p, '\\');
664 if (lastComponent && (lastComponent - p) > 1 &&
665 cm_ClientStrLen(lastComponent) > 1) {
666 *lastComponent = '\0';
669 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
670 userp, NULL, reqp, &iscp);
672 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
673 userp, NULL, reqp, scpp);
675 cm_ReleaseSCache(iscp);
677 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
678 userp, NULL, reqp, scpp);
682 cm_ReleaseSCache(substRootp);
683 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
690 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
691 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
692 userp, ioctlp->tidPathp, reqp, &substRootp);
694 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
700 lastComponent = cm_ClientStrRChr(relativePath, '\\');
701 if (lastComponent && (lastComponent - relativePath) > 1 &&
702 cm_ClientStrLen(lastComponent) > 1) {
703 *lastComponent = '\0';
706 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
707 userp, NULL, reqp, &iscp);
709 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
710 userp, NULL, reqp, scpp);
712 cm_ReleaseSCache(iscp);
714 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
715 userp, NULL, reqp, scpp);
718 cm_ReleaseSCache(substRootp);
719 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
727 cm_ReleaseSCache(substRootp);
729 /* and return success */
730 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
739 #define LEAF_SIZE 256
740 /* parse the passed-in file name and do a namei on its parent. If we fail,
741 * return an error code, otherwise return the vnode located in *scpp.
744 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
745 cm_scache_t **scpp, clientchar_t *leafp)
748 clientchar_t tbuffer[1024];
749 clientchar_t *tp, *jp;
750 cm_scache_t *substRootp = NULL;
751 clientchar_t *inpathp = NULL;
754 inpathdatap = ioctlp->ioctl.inDatap;
756 /* If the string starts with our UTF-8 prefix (which is the
757 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
758 strings), we assume that the provided path is UTF-8. Otherwise
759 we have to convert the string to UTF-8, since that is what we
760 want to use everywhere else.*/
762 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
764 /* String is UTF-8 */
765 inpathdatap += utf8_prefix_size;
766 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
768 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
772 /* Not a UTF-8 string */
773 /* TODO: If this is an OEM string, we should convert it to
775 if (smb_StoreAnsiFilenames) {
776 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
780 inpathp = malloc(cch * sizeof(clientchar_t));
781 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
783 TranslateExtendedChars(inpathdatap);
785 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
789 inpathp = malloc(cch * sizeof(clientchar_t));
790 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
794 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
795 tp = cm_ClientStrRChr(tbuffer, '\\');
796 jp = cm_ClientStrRChr(tbuffer, '/');
799 else if (jp && (tp - tbuffer) < (jp - tbuffer))
802 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
804 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
809 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
813 inpathp = NULL; /* We don't need this from this point on */
815 if (tbuffer[0] == tbuffer[1] &&
816 tbuffer[1] == '\\' &&
817 !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
818 cm_ClientStrLen(cm_NetbiosNameC)))
820 clientchar_t shareName[256];
821 clientchar_t *sharePath;
824 /* We may have found a UNC path.
825 * If the first component is the NetbiosName,
826 * then throw out the second component (the submount)
827 * since it had better expand into the value of ioctl->tidPathp
830 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
831 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
834 for (i = 0; *p && *p != '\\'; i++,p++ ) {
837 p++; /* skip past trailing slash */
838 shareName[i] = 0; /* terminate string */
840 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
842 /* we found a sharename, therefore use the resulting path */
843 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
844 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
845 userp, sharePath, reqp, &substRootp);
847 if (code) return code;
849 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
850 userp, NULL, reqp, scpp);
851 cm_ReleaseSCache(substRootp);
852 if (code) return code;
854 /* otherwise, treat the name as a cellname mounted off the afs root.
855 * This requires that we reconstruct the shareName string with
856 * leading and trailing slashes.
858 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
859 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
863 for (i = 1; *p && *p != '\\'; i++,p++ ) {
866 p++; /* skip past trailing slash */
867 shareName[i++] = '/'; /* add trailing slash */
868 shareName[i] = 0; /* terminate string */
870 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
871 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
872 userp, shareName, 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;
881 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->wdata,
882 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
883 userp, ioctlp->tidPathp, reqp, &substRootp);
884 if (code) return code;
886 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
887 userp, NULL, reqp, scpp);
888 cm_ReleaseSCache(substRootp);
889 if (code) return code;
892 /* # of bytes of path */
893 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
894 ioctlp->ioctl.inDatap += code;
896 /* and return success */
901 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
908 struct ClearToken ct;
914 int release_userp = 0;
915 clientchar_t *uname = NULL;
916 clientchar_t *smbname = NULL;
917 clientchar_t *wdir = NULL;
920 saveDataPtr = ioctlp->ioctl.inDatap;
922 cm_SkipIoctlPath(&ioctlp->ioctl);
924 tp = ioctlp->ioctl.inDatap;
927 memcpy(&ticketLen, tp, sizeof(ticketLen));
928 tp += sizeof(ticketLen);
929 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
930 return CM_ERROR_INVAL;
932 /* remember ticket and skip over it for now */
936 /* clear token size */
937 memcpy(&ctSize, tp, sizeof(ctSize));
938 tp += sizeof(ctSize);
939 if (ctSize != sizeof(struct ClearToken))
940 return CM_ERROR_INVAL;
943 memcpy(&ct, tp, ctSize);
945 if (ct.AuthHandle == -1)
946 ct.AuthHandle = 999; /* more rxvab compat stuff */
948 /* more stuff, if any */
949 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
950 /* flags: logon flag */
951 memcpy(&flags, tp, sizeof(int));
956 fschar_t * cellnamep;
959 temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
960 cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
961 cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
967 code = CM_ERROR_NOSUCHCELL;
970 tp += strlen(tp) + 1;
973 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
974 tp += strlen(tp) + 1;
976 if (flags & PIOCTL_LOGON) {
977 /* SMB user name with which to associate tokens */
978 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
979 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
980 osi_LogSaveClientString(smb_logp,uname),
981 osi_LogSaveClientString(smb_logp,smbname));
982 fprintf(stderr, "SMB name = %S\n", smbname);
983 tp += strlen(tp) + 1;
985 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%S]",
986 osi_LogSaveClientString(smb_logp, uname));
990 memcpy(&uuid, tp, sizeof(uuid));
991 if (!cm_FindTokenEvent(uuid, sessionKey)) {
992 code = CM_ERROR_INVAL;
996 cellp = cm_data.rootCellp;
997 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1000 if (flags & PIOCTL_LOGON) {
1001 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
1002 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1006 /* store the token */
1007 lock_ObtainMutex(&userp->mx);
1008 ucellp = cm_GetUCell(userp, cellp);
1009 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1010 ucellp->ticketLen = ticketLen;
1011 if (ucellp->ticketp)
1012 free(ucellp->ticketp); /* Discard old token if any */
1013 ucellp->ticketp = malloc(ticketLen);
1014 memcpy(ucellp->ticketp, ticket, ticketLen);
1016 * Get the session key from the RPC, rather than from the pioctl.
1019 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1021 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1022 ucellp->kvno = ct.AuthHandle;
1023 ucellp->expirationTime = ct.EndTimestamp;
1026 ucellp->uid = ANONYMOUSID;
1029 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1031 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1034 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1035 lock_ReleaseMutex(&userp->mx);
1037 if (flags & PIOCTL_LOGON) {
1038 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1041 cm_ResetACLCache(userp);
1045 cm_ReleaseUser(userp);
1059 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
1061 smb_user_t *uidp = ioctlp->uidp;
1063 if (uidp && uidp->unp) {
1066 cch = cm_ClientStringToUtf8(uidp->unp->name,
1067 cm_ClientStrLen(uidp->unp->name),
1069 ioctlp->ioctl.outDatap,
1070 (SMB_IOCTL_MAXDATA -
1071 (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1072 / sizeof(cm_utf8char_t));
1074 ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1081 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1086 cm_ioctlQueryOptions_t *optionsp;
1087 afs_uint32 flags = 0;
1091 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1092 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1093 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1095 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1097 cm_SkipIoctlPath(&ioctlp->ioctl);
1098 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1099 optionsp->fid.vnode, optionsp->fid.unique);
1100 code = cm_GetSCache(&fid, &scp, userp, &req);
1102 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1107 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1109 cm_ReleaseSCache(scp);
1114 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
1119 afs_uint32 flags = 0;
1123 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1127 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1129 cm_ReleaseSCache(scp);
1134 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1139 cm_ioctlQueryOptions_t *optionsp;
1140 afs_uint32 flags = 0;
1144 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1145 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1146 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1148 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1150 cm_SkipIoctlPath(&ioctlp->ioctl);
1151 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1152 optionsp->fid.vnode, optionsp->fid.unique);
1153 code = cm_GetSCache(&fid, &scp, userp, &req);
1155 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1160 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1162 cm_ReleaseSCache(scp);
1168 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1174 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1176 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1180 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
1185 cm_ioctlQueryOptions_t *optionsp;
1186 afs_uint32 flags = 0;
1190 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1191 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1192 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1194 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1196 cm_SkipIoctlPath(&ioctlp->ioctl);
1197 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1198 optionsp->fid.vnode, optionsp->fid.unique);
1199 code = cm_GetSCache(&fid, &scp, userp, &req);
1201 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1206 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1208 cm_ReleaseSCache(scp);
1214 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
1219 cm_ioctlQueryOptions_t *optionsp;
1220 afs_uint32 flags = 0;
1224 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1225 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1226 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1228 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1230 cm_SkipIoctlPath(&ioctlp->ioctl);
1231 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1232 optionsp->fid.vnode, optionsp->fid.unique);
1233 code = cm_GetSCache(&fid, &scp, userp, &req);
1235 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1240 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1242 cm_ReleaseSCache(scp);
1247 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1255 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1256 if (code) return code;
1258 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1259 cm_ReleaseSCache(scp);
1265 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1269 cm_ioctlQueryOptions_t *optionsp;
1270 afs_uint32 flags = 0;
1275 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1276 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1277 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1279 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1281 cm_SkipIoctlPath(&ioctlp->ioctl);
1282 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1283 optionsp->fid.vnode, optionsp->fid.unique);
1284 code = cm_GetSCache(&fid, &scp, userp, &req);
1286 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1291 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1293 cm_ReleaseSCache(scp);
1299 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
1304 cm_ioctlQueryOptions_t * optionsp;
1305 afs_uint32 flags = 0;
1309 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1310 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1311 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1313 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1317 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1319 cm_ReleaseSCache(scp);
1325 smb_IoctlGetFileType(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 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1341 cm_SkipIoctlPath(&ioctlp->ioctl);
1342 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1343 optionsp->fid.vnode, optionsp->fid.unique);
1344 code = cm_GetSCache(&fid, &scp, userp, &req);
1346 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1351 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1353 cm_ReleaseSCache(scp);
1359 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
1364 cm_ioctlQueryOptions_t *optionsp;
1365 afs_uint32 flags = 0;
1369 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1370 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1371 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1373 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1375 cm_SkipIoctlPath(&ioctlp->ioctl);
1376 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1377 optionsp->fid.vnode, optionsp->fid.unique);
1378 code = cm_GetSCache(&fid, &scp, userp, &req);
1380 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1385 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1387 cm_ReleaseSCache(scp);
1393 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1398 cm_ioctlQueryOptions_t *optionsp;
1399 afs_uint32 flags = 0;
1403 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1404 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1405 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1407 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1409 cm_SkipIoctlPath(&ioctlp->ioctl);
1410 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1411 optionsp->fid.vnode, optionsp->fid.unique);
1412 code = cm_GetSCache(&fid, &scp, userp, &req);
1414 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1419 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1421 cm_ReleaseSCache(scp);
1428 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1436 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1440 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1442 cm_ReleaseSCache(dscp);
1448 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1456 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1460 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1462 cm_ReleaseSCache(dscp);
1468 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
1470 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1472 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1476 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1478 /* we don't print anything superfluous, so we don't support the gag call */
1479 return CM_ERROR_INVAL;
1483 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1485 cm_SkipIoctlPath(&ioctlp->ioctl);
1487 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1490 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1492 cm_SkipIoctlPath(&ioctlp->ioctl);
1494 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1499 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1501 cm_SkipIoctlPath(&ioctlp->ioctl);
1503 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1507 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1509 cm_SkipIoctlPath(&ioctlp->ioctl);
1511 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1515 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1517 cm_SkipIoctlPath(&ioctlp->ioctl);
1519 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1523 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1525 cm_SkipIoctlPath(&ioctlp->ioctl);
1527 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1531 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1533 cm_SkipIoctlPath(&ioctlp->ioctl);
1535 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1539 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1541 cm_SkipIoctlPath(&ioctlp->ioctl);
1543 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1547 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1549 cm_SkipIoctlPath(&ioctlp->ioctl);
1551 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1555 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1557 cm_SkipIoctlPath(&ioctlp->ioctl);
1559 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1563 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1565 cm_SkipIoctlPath(&ioctlp->ioctl);
1567 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1571 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1573 cm_SkipIoctlPath(&ioctlp->ioctl);
1575 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1579 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1581 /* we ignore default asynchrony since we only have one way
1582 * of doing this today.
1588 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1592 clientchar_t leaf[LEAF_SIZE];
1597 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1601 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1603 cm_ReleaseSCache(dscp);
1608 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1612 clientchar_t leaf[LEAF_SIZE];
1617 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1618 if (code) return code;
1620 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1622 cm_ReleaseSCache(dscp);
1628 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1636 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1637 if (code) return code;
1639 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1641 cm_ReleaseSCache(dscp);
1646 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1647 {/*CHECK FOR VALID SYMLINK*/
1654 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1655 if (code) return code;
1657 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1659 cm_ReleaseSCache(dscp);
1665 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1673 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1674 if (code) return code;
1676 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1678 cm_ReleaseSCache(dscp);
1684 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
1686 cm_SkipIoctlPath(&ioctlp->ioctl);
1688 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1692 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1694 cm_SkipIoctlPath(&ioctlp->ioctl);
1696 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1701 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1703 cm_SkipIoctlPath(&ioctlp->ioctl);
1705 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1710 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1712 cm_SkipIoctlPath(&ioctlp->ioctl);
1714 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1719 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp)
1721 cm_SkipIoctlPath(&ioctlp->ioctl);
1723 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1727 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1729 cm_SkipIoctlPath(&ioctlp->ioctl);
1731 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1735 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp)
1737 cm_SkipIoctlPath(&ioctlp->ioctl);
1739 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1743 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
1745 cm_SkipIoctlPath(&ioctlp->ioctl);
1747 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1752 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
1754 cm_SkipIoctlPath(&ioctlp->ioctl);
1756 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1760 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1762 cm_SkipIoctlPath(&ioctlp->ioctl);
1764 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1768 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1770 cm_SkipIoctlPath(&ioctlp->ioctl);
1772 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1777 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
1779 cm_SkipIoctlPath(&ioctlp->ioctl);
1781 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1785 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
1790 cm_ioctlQueryOptions_t *optionsp;
1791 afs_uint32 flags = 0;
1795 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1796 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1797 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1799 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1801 cm_SkipIoctlPath(&ioctlp->ioctl);
1802 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1803 optionsp->fid.vnode, optionsp->fid.unique);
1804 code = cm_GetSCache(&fid, &scp, userp, &req);
1806 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1811 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1812 cm_ReleaseSCache(scp);
1817 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
1823 cm_SkipIoctlPath(&ioctlp->ioctl);
1825 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);