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;
92 smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
95 /* called to make a fid structure into an IOCTL fid structure */
97 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
100 cm_space_t *copyPrefix;
102 lock_ObtainMutex(&fidp->mx);
103 fidp->flags |= SMB_FID_IOCTL;
104 fidp->scp = &cm_data.fakeSCache;
105 cm_HoldSCache(fidp->scp);
106 if (fidp->ioctlp == NULL) {
107 iop = malloc(sizeof(*iop));
108 memset(iop, 0, sizeof(*iop));
113 copyPrefix = cm_GetSpace();
114 memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
115 fidp->ioctlp->prefix = copyPrefix;
117 lock_ReleaseMutex(&fidp->mx);
120 /* called when we receive a read call, does the send of the received data if
121 * this is the first read call. This is the function that actually makes the
122 * call to the ioctl code.
125 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
128 smb_ioctlProc_t *procp = NULL;
131 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
132 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
133 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAOUT;
135 /* do the call now, or fail if we didn't get an opcode, or
136 * enough of an opcode.
138 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
139 return CM_ERROR_INVAL;
140 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
141 ioctlp->ioctl.inDatap += sizeof(afs_int32);
143 osi_Log1(afsd_logp, "smb_IoctlPrepareRead opcode 0x%x", opcode);
144 /* check for opcode out of bounds */
145 if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS) {
146 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - invalid opcode");
147 return CM_ERROR_TOOBIG;
150 /* check for no such proc */
151 procp = smb_ioctlProcsp[opcode];
153 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - unassigned opcode");
154 return CM_ERROR_INVAL;
156 /* otherwise, make the call */
157 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
158 code = (*procp)(ioctlp, userp, pflags);
159 osi_Log1(afsd_logp, "smb_IoctlPrepareRead operation returns code 0x%x", code);
161 /* copy in return code */
162 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
163 } else if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAOUT)) {
164 osi_Log0(afsd_logp, "Ioctl invalid state - dataout expected");
165 return CM_ERROR_INVAL;
171 /* called when we receive a write call. If this is the first write call after
172 * a series of reads (or the very first call), then we start a new call.
173 * We also ensure that things are properly initialized for the start of a call.
176 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
178 /* make sure the buffer(s) are allocated */
179 if (!ioctlp->ioctl.inAllocp)
180 ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
181 if (!ioctlp->ioctl.outAllocp)
182 ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
184 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
185 (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
186 (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
188 /* and make sure that we've reset our state for the new incoming request */
189 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
190 ioctlp->ioctl.inCopied = 0;
191 ioctlp->ioctl.outCopied = 0;
192 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
193 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
194 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
195 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAOUT;
199 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
201 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
205 afs_int32 leftToCopy;
209 cm_user_t *userp = NULL;
214 count = smb_GetSMBParm(inp, 1);
216 /* Get the user and determine if it is the local machine account */
217 smbp = (smb_t *) inp;
218 uidp = smb_FindUID(vcp, smbp->uid, 0);
220 isSystem = smb_userIsLocalSystem(uidp);
221 userp = smb_GetUserFromUID(uidp);
222 smb_ReleaseUID(uidp);
226 userp = cm_rootUserp;
231 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
233 cm_ReleaseUser(userp);
234 return CM_ERROR_NOSUCHPATH;
237 /* turn the connection around, if required */
238 code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
241 cm_ReleaseUser(userp);
245 leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
246 if (leftToCopy < 0) {
247 osi_Log0(afsd_logp, "smb_IoctlRead leftToCopy went negative");
248 cm_ReleaseUser(userp);
249 return CM_ERROR_INVAL;
251 if (count > leftToCopy)
254 /* now set the parms for a read of count bytes */
255 smb_SetSMBParm(outp, 0, count);
256 smb_SetSMBParm(outp, 1, 0);
257 smb_SetSMBParm(outp, 2, 0);
258 smb_SetSMBParm(outp, 3, 0);
259 smb_SetSMBParm(outp, 4, 0);
261 smb_SetSMBDataLength(outp, count+3);
263 op = smb_GetSMBData(outp, NULL);
265 *op++ = (char)(count & 0xff);
266 *op++ = (char)((count >> 8) & 0xff);
268 /* now copy the data into the response packet */
269 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
271 /* and adjust the counters */
272 iop->ioctl.outCopied += count;
274 cm_ReleaseUser(userp);
279 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
283 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
289 int inDataBlockCount;
292 count = smb_GetSMBParm(inp, 1);
295 smb_IoctlPrepareWrite(fidp, iop);
297 op = smb_GetSMBData(inp, NULL);
298 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
300 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
301 code = CM_ERROR_TOOBIG;
306 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
309 iop->ioctl.inCopied += count;
312 /* return # of bytes written */
314 smb_SetSMBParm(outp, 0, count);
315 smb_SetSMBDataLength(outp, 0);
321 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
325 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
331 int inDataBlockCount;
334 count = smb_GetSMBParm(inp, 10);
337 smb_IoctlPrepareWrite(fidp, iop);
339 op = inp->data + smb_GetSMBParm(inp, 11);
340 inDataBlockCount = count;
342 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
343 code = CM_ERROR_TOOBIG;
348 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
351 iop->ioctl.inCopied += count;
354 /* return # of bytes written */
356 smb_SetSMBParm(outp, 2, count);
357 smb_SetSMBParm(outp, 3, 0); /* reserved */
358 smb_SetSMBParm(outp, 4, 0); /* reserved */
359 smb_SetSMBParm(outp, 5, 0); /* reserved */
360 smb_SetSMBDataLength(outp, 0);
367 /* called from V3 read to handle IOCTL descriptor reads */
369 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
372 unsigned short count;
380 count = smb_GetSMBParm(inp, 5);
382 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
384 return CM_ERROR_BADSMB;
385 userp = smb_GetUserFromUID(uidp);
386 osi_assertx(userp != NULL, "null cm_user_t");
388 if (uidp && uidp->unp) {
389 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %S",
391 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
394 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
395 uidp->userID, userp);
397 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
401 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
404 smb_ReleaseUID(uidp);
405 cm_ReleaseUser(userp);
406 return CM_ERROR_NOSUCHPATH;
409 code = smb_IoctlPrepareRead(fidp, iop, userp, 0);
412 smb_ReleaseUID(uidp);
415 cm_ReleaseUser(userp);
419 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
420 if (leftToCopy < 0) {
421 osi_Log0(afsd_logp, "smb_IoctlV3Read leftToCopy went negative");
422 cm_ReleaseUser(userp);
423 return CM_ERROR_INVAL;
425 if (count > leftToCopy)
426 count = (unsigned short)leftToCopy;
428 /* 0 and 1 are reserved for request chaining, were setup by our caller,
429 * and will be further filled in after we return.
431 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
432 smb_SetSMBParm(outp, 3, 0); /* resvd */
433 smb_SetSMBParm(outp, 4, 0); /* resvd */
434 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
435 /* fill in #6 when we have all the parameters' space reserved */
436 smb_SetSMBParm(outp, 7, 0); /* resv'd */
437 smb_SetSMBParm(outp, 8, 0); /* resv'd */
438 smb_SetSMBParm(outp, 9, 0); /* resv'd */
439 smb_SetSMBParm(outp, 10, 0); /* resv'd */
440 smb_SetSMBParm(outp, 11, 0); /* reserved */
442 /* get op ptr after putting in the last parm, since otherwise we don't
443 * know where the data really is.
445 op = smb_GetSMBData(outp, NULL);
447 /* now fill in offset from start of SMB header to first data byte (to op) */
448 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
450 /* set the packet data length the count of the # of bytes */
451 smb_SetSMBDataLength(outp, count);
453 /* now copy the data into the response packet */
454 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
456 /* and adjust the counters */
457 iop->ioctl.outCopied += count;
459 /* and cleanup things */
460 cm_ReleaseUser(userp);
465 /* called from Read Raw to handle IOCTL descriptor reads */
467 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
479 userp = smb_GetUserFromVCP(vcp, inp);
482 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
483 if (uidp && uidp->unp) {
484 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
486 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
488 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
489 uidp->userID, userp);
491 osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
495 smb_ReleaseUID(uidp);
497 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
499 code = CM_ERROR_NOSUCHPATH;
503 code = smb_IoctlPrepareRead(fidp, iop, userp, 0);
508 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
509 if (leftToCopy < 0) {
510 osi_Log0(afsd_logp, "smb_IoctlReadRaw leftToCopy went negative");
511 code = CM_ERROR_INVAL;
516 memset(ncbp, 0, sizeof(NCB));
518 ncbp->ncb_length = (unsigned short) leftToCopy;
519 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
520 ncbp->ncb_command = NCBSEND;
521 /*ncbp->ncb_lana_num = smb_LANadapter;*/
522 ncbp->ncb_lana_num = vcp->lana;
524 ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
525 code = Netbios(ncbp);
528 osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
531 cm_ReleaseUser(userp);
536 /* parse the passed-in file name and do a namei on it. If we fail,
537 * return an error code, otherwise return the vnode located in *scpp.
539 #define CM_PARSE_FLAG_LITERAL 1
542 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
543 cm_scache_t **scpp, afs_uint32 flags)
546 cm_scache_t *substRootp = NULL;
547 cm_scache_t *iscp = NULL;
549 clientchar_t *relativePath = NULL;
550 clientchar_t *lastComponent = NULL;
551 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
553 inPath = ioctlp->ioctl.inDatap;
554 /* setup the next data value for the caller to use */
555 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
557 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
559 /* This is usually the file name, but for StatMountPoint it is the path. */
560 /* ioctlp->ioctl.inDatap can be either of the form:
563 * \\netbios-name\submount\path\.
564 * \\netbios-name\submount\path\file
567 /* We do not perform path name translation on the ioctl path data
568 * because these paths were not translated by Windows through the
569 * file system API. Therefore, they are not OEM characters but
570 * whatever the display character set is.
573 // TranslateExtendedChars(relativePath);
575 /* This is usually nothing, but for StatMountPoint it is the file name. */
576 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
578 /* If the string starts with our UTF-8 prefix (which is the
579 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
580 strings), we assume that the provided path is UTF-8. Otherwise
581 we have to convert the string to UTF-8, since that is what we
582 want to use everywhere else.*/
584 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
585 /* String is UTF-8 */
586 inPath += utf8_prefix_size;
587 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
589 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
593 /* Not a UTF-8 string */
594 /* TODO: If this is an OEM string, we should convert it to
596 if (smb_StoreAnsiFilenames) {
597 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
601 relativePath = malloc(cch * sizeof(clientchar_t));
602 cm_AnsiToClientString(inPath, -1, relativePath, cch);
604 TranslateExtendedChars(inPath);
606 cch = cm_OemToClientString(inPath, -1, NULL, 0);
610 relativePath = malloc(cch * sizeof(clientchar_t));
611 cm_OemToClientString(inPath, -1, relativePath, cch);
615 if (relativePath[0] == relativePath[1] &&
616 relativePath[1] == '\\' &&
617 !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
618 cm_ClientStrLen(cm_NetbiosNameC)))
620 clientchar_t shareName[256];
621 clientchar_t *sharePath;
624 /* We may have found a UNC path.
625 * If the first component is the NetbiosName,
626 * then throw out the second component (the submount)
627 * since it had better expand into the value of ioctl->tidPathp
630 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1; /* buffer overflow vuln.? */
631 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
634 for (i = 0; *p && *p != '\\'; i++,p++ ) {
637 p++; /* skip past trailing slash */
638 shareName[i] = 0; /* terminate string */
640 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
642 /* we found a sharename, therefore use the resulting path */
643 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
644 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
645 userp, sharePath, reqp, &substRootp);
648 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
654 lastComponent = cm_ClientStrRChr(p, '\\');
655 if (lastComponent && (lastComponent - p) > 1 &&
656 cm_ClientStrLen(lastComponent) > 1) {
657 *lastComponent = '\0';
660 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
661 userp, NULL, reqp, &iscp);
663 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
664 userp, NULL, reqp, scpp);
666 cm_ReleaseSCache(iscp);
668 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
669 userp, NULL, reqp, scpp);
671 cm_ReleaseSCache(substRootp);
673 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
679 /* otherwise, treat the name as a cellname mounted off the afs root.
680 * This requires that we reconstruct the shareName string with
681 * leading and trailing slashes.
683 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
684 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
688 for (i = 1; *p && *p != '\\'; i++,p++ ) {
691 p++; /* skip past trailing slash */
692 shareName[i++] = '/'; /* add trailing slash */
693 shareName[i] = 0; /* terminate string */
696 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
697 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
698 userp, shareName, reqp, &substRootp);
700 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
706 lastComponent = cm_ClientStrRChr(p, '\\');
707 if (lastComponent && (lastComponent - p) > 1 &&
708 cm_ClientStrLen(lastComponent) > 1) {
709 *lastComponent = '\0';
712 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
713 userp, NULL, reqp, &iscp);
715 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
716 userp, NULL, reqp, scpp);
718 cm_ReleaseSCache(iscp);
720 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
721 userp, NULL, reqp, scpp);
725 cm_ReleaseSCache(substRootp);
726 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
733 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
734 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
735 userp, ioctlp->tidPathp, reqp, &substRootp);
737 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
743 lastComponent = cm_ClientStrRChr(relativePath, '\\');
744 if (lastComponent && (lastComponent - relativePath) > 1 &&
745 cm_ClientStrLen(lastComponent) > 1) {
746 *lastComponent = '\0';
749 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
750 userp, NULL, reqp, &iscp);
752 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
753 userp, NULL, reqp, scpp);
755 cm_ReleaseSCache(iscp);
757 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
758 userp, NULL, reqp, scpp);
761 cm_ReleaseSCache(substRootp);
762 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
770 cm_ReleaseSCache(substRootp);
775 /* Ensure that the status object is up to date */
776 lock_ObtainWrite(&(*scpp)->rw);
777 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
778 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
780 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
781 lock_ReleaseWrite(&(*scpp)->rw);
783 /* and return success */
784 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
790 #define LEAF_SIZE 256
791 /* parse the passed-in file name and do a namei on its parent. If we fail,
792 * return an error code, otherwise return the vnode located in *scpp.
795 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
796 cm_scache_t **scpp, clientchar_t *leafp)
799 clientchar_t tbuffer[1024];
800 clientchar_t *tp, *jp;
801 cm_scache_t *substRootp = NULL;
802 clientchar_t *inpathp = NULL;
805 inpathdatap = ioctlp->ioctl.inDatap;
807 /* If the string starts with our UTF-8 prefix (which is the
808 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
809 strings), we assume that the provided path is UTF-8. Otherwise
810 we have to convert the string to UTF-8, since that is what we
811 want to use everywhere else.*/
813 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
815 /* String is UTF-8 */
816 inpathdatap += utf8_prefix_size;
817 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
819 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
823 /* Not a UTF-8 string */
824 /* TODO: If this is an OEM string, we should convert it to
826 if (smb_StoreAnsiFilenames) {
827 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
831 inpathp = malloc(cch * sizeof(clientchar_t));
832 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
834 TranslateExtendedChars(inpathdatap);
836 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
840 inpathp = malloc(cch * sizeof(clientchar_t));
841 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
845 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
846 tp = cm_ClientStrRChr(tbuffer, '\\');
847 jp = cm_ClientStrRChr(tbuffer, '/');
850 else if (jp && (tp - tbuffer) < (jp - tbuffer))
853 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
855 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
860 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
864 inpathp = NULL; /* We don't need this from this point on */
866 if (tbuffer[0] == tbuffer[1] &&
867 tbuffer[1] == '\\' &&
868 !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
869 cm_ClientStrLen(cm_NetbiosNameC)))
871 clientchar_t shareName[256];
872 clientchar_t *sharePath;
875 /* We may have found a UNC path.
876 * If the first component is the NetbiosName,
877 * then throw out the second component (the submount)
878 * since it had better expand into the value of ioctl->tidPathp
881 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
882 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
885 for (i = 0; *p && *p != '\\'; i++,p++ ) {
888 p++; /* skip past trailing slash */
889 shareName[i] = 0; /* terminate string */
891 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
893 /* we found a sharename, therefore use the resulting path */
894 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
895 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
896 userp, sharePath, reqp, &substRootp);
898 if (code) return code;
900 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
901 userp, NULL, reqp, scpp);
902 cm_ReleaseSCache(substRootp);
903 if (code) return code;
905 /* otherwise, treat the name as a cellname mounted off the afs root.
906 * This requires that we reconstruct the shareName string with
907 * leading and trailing slashes.
909 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
910 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
914 for (i = 1; *p && *p != '\\'; i++,p++ ) {
917 p++; /* skip past trailing slash */
918 shareName[i++] = '/'; /* add trailing slash */
919 shareName[i] = 0; /* terminate string */
921 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
922 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
923 userp, shareName, reqp, &substRootp);
924 if (code) return code;
926 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
927 userp, NULL, reqp, scpp);
928 cm_ReleaseSCache(substRootp);
929 if (code) return code;
932 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
933 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
934 userp, ioctlp->tidPathp, reqp, &substRootp);
935 if (code) return code;
937 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
938 userp, NULL, reqp, scpp);
939 cm_ReleaseSCache(substRootp);
940 if (code) return code;
943 /* # of bytes of path */
944 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
945 ioctlp->ioctl.inDatap += code;
947 /* Ensure that the status object is up to date */
948 lock_ObtainWrite(&(*scpp)->rw);
949 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
950 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
952 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
953 lock_ReleaseWrite(&(*scpp)->rw);
955 /* and return success */
960 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
967 struct ClearToken ct;
973 int release_userp = 0;
974 clientchar_t *uname = NULL;
975 clientchar_t *smbname = NULL;
976 clientchar_t *wdir = NULL;
979 saveDataPtr = ioctlp->ioctl.inDatap;
981 cm_SkipIoctlPath(&ioctlp->ioctl);
983 tp = ioctlp->ioctl.inDatap;
986 memcpy(&ticketLen, tp, sizeof(ticketLen));
987 tp += sizeof(ticketLen);
988 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
989 return CM_ERROR_INVAL;
991 /* remember ticket and skip over it for now */
995 /* clear token size */
996 memcpy(&ctSize, tp, sizeof(ctSize));
997 tp += sizeof(ctSize);
998 if (ctSize != sizeof(struct ClearToken))
999 return CM_ERROR_INVAL;
1002 memcpy(&ct, tp, ctSize);
1004 if (ct.AuthHandle == -1)
1005 ct.AuthHandle = 999; /* more rxvab compat stuff */
1007 /* more stuff, if any */
1008 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
1009 /* flags: logon flag */
1010 memcpy(&flags, tp, sizeof(int));
1015 fschar_t * cellnamep;
1016 clientchar_t * temp;
1018 temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1019 cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
1020 cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
1026 code = CM_ERROR_NOSUCHCELL;
1029 tp += strlen(tp) + 1;
1032 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1033 tp += strlen(tp) + 1;
1035 if (flags & PIOCTL_LOGON) {
1036 /* SMB user name with which to associate tokens */
1037 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1038 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
1039 osi_LogSaveClientString(smb_logp,uname),
1040 osi_LogSaveClientString(smb_logp,smbname));
1041 fprintf(stderr, "SMB name = %S\n", smbname);
1042 tp += strlen(tp) + 1;
1044 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%S]",
1045 osi_LogSaveClientString(smb_logp, uname));
1049 memcpy(&uuid, tp, sizeof(uuid));
1050 if (!cm_FindTokenEvent(uuid, sessionKey)) {
1051 code = CM_ERROR_INVAL;
1055 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1056 code = CM_ERROR_NOACCESS;
1060 cellp = cm_data.rootCellp;
1061 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1064 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1065 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
1066 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1070 /* store the token */
1071 lock_ObtainMutex(&userp->mx);
1072 ucellp = cm_GetUCell(userp, cellp);
1073 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1074 ucellp->ticketLen = ticketLen;
1075 if (ucellp->ticketp)
1076 free(ucellp->ticketp); /* Discard old token if any */
1077 ucellp->ticketp = malloc(ticketLen);
1078 memcpy(ucellp->ticketp, ticket, ticketLen);
1080 * Get the session key from the RPC, rather than from the pioctl.
1083 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1085 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1086 ucellp->kvno = ct.AuthHandle;
1087 ucellp->expirationTime = ct.EndTimestamp;
1090 ucellp->uid = ANONYMOUSID;
1093 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1095 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1098 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1099 lock_ReleaseMutex(&userp->mx);
1101 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1102 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1105 cm_ResetACLCache(cellp, userp);
1108 SecureZeroMemory(sessionKey, sizeof(sessionKey));
1111 cm_ReleaseUser(userp);
1125 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1127 smb_user_t *uidp = ioctlp->uidp;
1129 if (uidp && uidp->unp) {
1132 cch = cm_ClientStringToUtf8(uidp->unp->name,
1134 ioctlp->ioctl.outDatap,
1135 (SMB_IOCTL_MAXDATA -
1136 (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1137 / sizeof(cm_utf8char_t));
1139 ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1146 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1151 cm_ioctlQueryOptions_t *optionsp;
1152 afs_uint32 flags = 0;
1156 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1157 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1158 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1160 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1162 cm_SkipIoctlPath(&ioctlp->ioctl);
1163 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1164 optionsp->fid.vnode, optionsp->fid.unique);
1165 code = cm_GetSCache(&fid, &scp, userp, &req);
1167 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1173 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1175 cm_ReleaseSCache(scp);
1180 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1185 afs_uint32 flags = 0;
1189 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1193 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1195 cm_ReleaseSCache(scp);
1200 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1205 cm_ioctlQueryOptions_t *optionsp;
1206 afs_uint32 flags = 0;
1210 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1211 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1212 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1214 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1216 cm_SkipIoctlPath(&ioctlp->ioctl);
1217 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1218 optionsp->fid.vnode, optionsp->fid.unique);
1219 code = cm_GetSCache(&fid, &scp, userp, &req);
1221 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1226 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1228 cm_ReleaseSCache(scp);
1234 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1240 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1242 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1246 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1251 cm_ioctlQueryOptions_t *optionsp;
1252 afs_uint32 flags = 0;
1256 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1257 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1258 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1260 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1262 cm_SkipIoctlPath(&ioctlp->ioctl);
1263 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1264 optionsp->fid.vnode, optionsp->fid.unique);
1265 code = cm_GetSCache(&fid, &scp, userp, &req);
1267 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1272 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1274 cm_ReleaseSCache(scp);
1280 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1285 cm_ioctlQueryOptions_t *optionsp;
1286 afs_uint32 flags = 0;
1290 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1291 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1292 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1294 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1296 cm_SkipIoctlPath(&ioctlp->ioctl);
1297 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1298 optionsp->fid.vnode, optionsp->fid.unique);
1299 code = cm_GetSCache(&fid, &scp, userp, &req);
1301 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1306 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1308 cm_ReleaseSCache(scp);
1313 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1321 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1322 if (code) return code;
1324 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1325 cm_ReleaseSCache(scp);
1331 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1335 cm_ioctlQueryOptions_t *optionsp;
1336 afs_uint32 flags = 0;
1341 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1342 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1343 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1345 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1347 cm_SkipIoctlPath(&ioctlp->ioctl);
1348 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1349 optionsp->fid.vnode, optionsp->fid.unique);
1350 code = cm_GetSCache(&fid, &scp, userp, &req);
1352 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1357 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1359 cm_ReleaseSCache(scp);
1365 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1370 cm_ioctlQueryOptions_t * optionsp;
1371 afs_uint32 flags = 0;
1375 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1376 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1377 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1379 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1383 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1385 cm_ReleaseSCache(scp);
1391 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1396 cm_ioctlQueryOptions_t * optionsp;
1397 afs_uint32 flags = 0;
1401 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1402 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1403 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1405 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1407 cm_SkipIoctlPath(&ioctlp->ioctl);
1408 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1409 optionsp->fid.vnode, optionsp->fid.unique);
1410 code = cm_GetSCache(&fid, &scp, userp, &req);
1412 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1417 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1419 cm_ReleaseSCache(scp);
1425 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1430 cm_ioctlQueryOptions_t *optionsp;
1431 afs_uint32 flags = 0;
1435 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1436 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1437 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1439 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1441 cm_SkipIoctlPath(&ioctlp->ioctl);
1442 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1443 optionsp->fid.vnode, optionsp->fid.unique);
1444 code = cm_GetSCache(&fid, &scp, userp, &req);
1446 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1451 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1453 cm_ReleaseSCache(scp);
1459 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1464 cm_ioctlQueryOptions_t *optionsp;
1465 afs_uint32 flags = 0;
1469 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1470 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1471 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1473 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1475 cm_SkipIoctlPath(&ioctlp->ioctl);
1476 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1477 optionsp->fid.vnode, optionsp->fid.unique);
1478 code = cm_GetSCache(&fid, &scp, userp, &req);
1480 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1485 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1487 cm_ReleaseSCache(scp);
1494 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1502 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1506 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1508 cm_ReleaseSCache(dscp);
1514 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1522 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1526 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1528 cm_ReleaseSCache(dscp);
1534 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1536 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1538 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1542 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1544 /* we don't print anything superfluous, so we don't support the gag call */
1545 return CM_ERROR_INVAL;
1549 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1551 cm_SkipIoctlPath(&ioctlp->ioctl);
1553 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1556 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1558 cm_SkipIoctlPath(&ioctlp->ioctl);
1560 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1565 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1567 cm_SkipIoctlPath(&ioctlp->ioctl);
1569 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1573 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1575 cm_SkipIoctlPath(&ioctlp->ioctl);
1577 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1581 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1583 cm_SkipIoctlPath(&ioctlp->ioctl);
1585 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1589 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1591 cm_SkipIoctlPath(&ioctlp->ioctl);
1593 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1597 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1599 cm_SkipIoctlPath(&ioctlp->ioctl);
1601 return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1605 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1607 cm_SkipIoctlPath(&ioctlp->ioctl);
1609 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1613 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1615 cm_SkipIoctlPath(&ioctlp->ioctl);
1617 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1621 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1623 cm_SkipIoctlPath(&ioctlp->ioctl);
1625 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1629 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1631 cm_SkipIoctlPath(&ioctlp->ioctl);
1633 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1637 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1639 cm_SkipIoctlPath(&ioctlp->ioctl);
1641 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1645 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1647 cm_SkipIoctlPath(&ioctlp->ioctl);
1649 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1653 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1655 /* we ignore default asynchrony since we only have one way
1656 * of doing this today.
1662 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1666 clientchar_t leaf[LEAF_SIZE];
1671 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1675 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1677 cm_ReleaseSCache(dscp);
1682 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1686 clientchar_t leaf[LEAF_SIZE];
1691 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1692 if (code) return code;
1694 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1696 cm_ReleaseSCache(dscp);
1702 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1710 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1711 if (code) return code;
1713 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1715 cm_ReleaseSCache(dscp);
1720 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1721 {/*CHECK FOR VALID SYMLINK*/
1728 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1729 if (code) return code;
1731 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1733 cm_ReleaseSCache(dscp);
1739 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1747 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1748 if (code) return code;
1750 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1752 cm_ReleaseSCache(dscp);
1758 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1760 cm_SkipIoctlPath(&ioctlp->ioctl);
1762 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1766 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1768 cm_SkipIoctlPath(&ioctlp->ioctl);
1770 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1775 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1777 cm_SkipIoctlPath(&ioctlp->ioctl);
1779 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1784 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1786 cm_SkipIoctlPath(&ioctlp->ioctl);
1788 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1793 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1795 cm_SkipIoctlPath(&ioctlp->ioctl);
1797 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1801 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1803 cm_SkipIoctlPath(&ioctlp->ioctl);
1805 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1809 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1811 cm_SkipIoctlPath(&ioctlp->ioctl);
1813 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1817 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1819 cm_SkipIoctlPath(&ioctlp->ioctl);
1821 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1826 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1828 cm_SkipIoctlPath(&ioctlp->ioctl);
1830 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1834 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1836 cm_SkipIoctlPath(&ioctlp->ioctl);
1838 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1842 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1844 cm_SkipIoctlPath(&ioctlp->ioctl);
1846 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1851 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1853 cm_SkipIoctlPath(&ioctlp->ioctl);
1855 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1859 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1864 cm_ioctlQueryOptions_t *optionsp;
1865 afs_uint32 flags = 0;
1869 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1870 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1871 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1873 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1875 cm_SkipIoctlPath(&ioctlp->ioctl);
1876 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1877 optionsp->fid.vnode, optionsp->fid.unique);
1878 code = cm_GetSCache(&fid, &scp, userp, &req);
1880 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1885 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1886 cm_ReleaseSCache(scp);
1891 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1897 cm_SkipIoctlPath(&ioctlp->ioctl);
1899 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
1905 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1909 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1914 cm_ioctlQueryOptions_t *optionsp;
1915 afs_uint32 flags = 0;
1919 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1921 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1922 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1924 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1926 cm_SkipIoctlPath(&ioctlp->ioctl);
1927 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1928 optionsp->fid.vnode, optionsp->fid.unique);
1929 code = cm_GetSCache(&fid, &scp, userp, &req);
1931 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1936 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1939 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
1941 cm_ReleaseSCache(scp);
1949 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
1953 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1958 cm_ioctlQueryOptions_t *optionsp;
1959 afs_uint32 flags = 0;
1963 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1965 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1966 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1968 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1970 cm_SkipIoctlPath(&ioctlp->ioctl);
1971 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1972 optionsp->fid.vnode, optionsp->fid.unique);
1973 code = cm_GetSCache(&fid, &scp, userp, &req);
1975 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1980 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
1983 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
1985 cm_ReleaseSCache(scp);