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 <afsconfig.h>
11 #include <afs/param.h>
32 #include "afs/afsrpc.h"
35 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
41 for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
42 smb_ioctlProcsp[i] = NULL;
44 smb_ioctlProcsp[VIOCGETAL] = smb_IoctlGetACL;
45 smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = smb_IoctlGetFileCellName;
46 smb_ioctlProcsp[VIOCSETAL] = smb_IoctlSetACL;
47 smb_ioctlProcsp[VIOC_FLUSHVOLUME] = smb_IoctlFlushVolume;
48 smb_ioctlProcsp[VIOCFLUSH] = smb_IoctlFlushFile;
49 smb_ioctlProcsp[VIOCSETVOLSTAT] = smb_IoctlSetVolumeStatus;
50 smb_ioctlProcsp[VIOCGETVOLSTAT] = smb_IoctlGetVolumeStatus;
51 smb_ioctlProcsp[VIOCWHEREIS] = smb_IoctlWhereIs;
52 smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = smb_IoctlStatMountPoint;
53 smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = smb_IoctlDeleteMountPoint;
54 smb_ioctlProcsp[VIOCCKSERV] = smb_IoctlCheckServers;
55 smb_ioctlProcsp[VIOC_GAG] = smb_IoctlGag;
56 smb_ioctlProcsp[VIOCCKBACK] = smb_IoctlCheckVolumes;
57 smb_ioctlProcsp[VIOCSETCACHESIZE] = smb_IoctlSetCacheSize;
58 smb_ioctlProcsp[VIOCGETCACHEPARMS] = smb_IoctlGetCacheParms;
59 smb_ioctlProcsp[VIOCGETCELL] = smb_IoctlGetCell;
60 smb_ioctlProcsp[VIOCNEWCELL] = smb_IoctlNewCell;
61 smb_ioctlProcsp[VIOC_GET_WS_CELL] = smb_IoctlGetWsCell;
62 smb_ioctlProcsp[VIOC_AFS_SYSNAME] = smb_IoctlSysName;
63 smb_ioctlProcsp[VIOC_GETCELLSTATUS] = smb_IoctlGetCellStatus;
64 smb_ioctlProcsp[VIOC_SETCELLSTATUS] = smb_IoctlSetCellStatus;
65 smb_ioctlProcsp[VIOC_SETSPREFS] = smb_IoctlSetSPrefs;
66 smb_ioctlProcsp[VIOC_GETSPREFS] = smb_IoctlGetSPrefs;
67 smb_ioctlProcsp[VIOC_STOREBEHIND] = smb_IoctlStoreBehind;
68 smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = smb_IoctlCreateMountPoint;
69 smb_ioctlProcsp[VIOC_TRACECTL] = smb_IoctlTraceControl;
70 smb_ioctlProcsp[VIOCSETTOK] = smb_IoctlSetToken;
71 smb_ioctlProcsp[VIOCGETTOK] = smb_IoctlGetTokenIter;
72 smb_ioctlProcsp[VIOCNEWGETTOK] = smb_IoctlGetToken;
73 smb_ioctlProcsp[VIOCDELTOK] = smb_IoctlDelToken;
74 smb_ioctlProcsp[VIOCDELALLTOK] = smb_IoctlDelAllToken;
75 smb_ioctlProcsp[VIOC_SYMLINK] = smb_IoctlSymlink;
76 smb_ioctlProcsp[VIOC_LISTSYMLINK] = smb_IoctlListlink;
77 smb_ioctlProcsp[VIOC_DELSYMLINK] = smb_IoctlDeletelink;
78 smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = smb_IoctlMakeSubmount;
79 smb_ioctlProcsp[VIOC_GETRXKCRYPT] = smb_IoctlGetRxkcrypt;
80 smb_ioctlProcsp[VIOC_SETRXKCRYPT] = smb_IoctlSetRxkcrypt;
81 smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
82 smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = smb_IoctlMemoryDump;
83 smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
84 smb_ioctlProcsp[VIOC_FLUSHALL] = smb_IoctlFlushAllVolumes;
85 smb_ioctlProcsp[VIOCGETFID] = smb_IoctlGetFid;
86 smb_ioctlProcsp[VIOCGETOWNER] = smb_IoctlGetOwner;
87 smb_ioctlProcsp[VIOC_RXSTAT_PROC] = smb_IoctlRxStatProcess;
88 smb_ioctlProcsp[VIOC_RXSTAT_PEER] = smb_IoctlRxStatPeer;
89 smb_ioctlProcsp[VIOC_UUIDCTL] = smb_IoctlUUIDControl;
90 smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = smb_IoctlPathAvailability;
91 smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
92 smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
93 smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
94 smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
95 smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
96 smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
97 smb_ioctlProcsp[VIOC_SETUNIXMODE] = smb_IoctlSetUnixMode;
98 smb_ioctlProcsp[VIOC_GETUNIXMODE] = smb_IoctlSetUnixMode;
101 /* called to make a fid structure into an IOCTL fid structure */
103 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
106 cm_space_t *copyPrefix;
108 lock_ObtainMutex(&fidp->mx);
109 fidp->flags |= SMB_FID_IOCTL;
110 fidp->scp = &cm_data.fakeSCache;
111 cm_HoldSCache(fidp->scp);
112 if (fidp->ioctlp == NULL) {
113 iop = malloc(sizeof(*iop));
114 memset(iop, 0, sizeof(*iop));
119 copyPrefix = cm_GetSpace();
120 memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
121 fidp->ioctlp->prefix = copyPrefix;
123 lock_ReleaseMutex(&fidp->mx);
126 /* called when we receive a read call, does the send of the received data if
127 * this is the first read call. This is the function that actually makes the
128 * call to the ioctl code.
131 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
134 smb_ioctlProc_t *procp = NULL;
137 if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
138 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
139 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAOUT;
141 /* do the call now, or fail if we didn't get an opcode, or
142 * enough of an opcode.
144 if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
145 return CM_ERROR_INVAL;
146 memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
147 ioctlp->ioctl.inDatap += sizeof(afs_int32);
149 osi_Log1(afsd_logp, "smb_IoctlPrepareRead opcode 0x%x", opcode);
150 /* check for opcode out of bounds */
151 if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS) {
152 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - invalid opcode");
153 return CM_ERROR_TOOBIG;
156 /* check for no such proc */
157 procp = smb_ioctlProcsp[opcode];
159 osi_Log0(afsd_logp, "smb_IoctlPrepareRead - unassigned opcode");
160 return CM_ERROR_INVAL;
162 /* otherwise, make the call */
163 ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
164 code = (*procp)(ioctlp, userp, pflags);
165 osi_Log1(afsd_logp, "smb_IoctlPrepareRead operation returns code 0x%x", code);
167 /* copy in return code */
168 memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
169 } else if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAOUT)) {
170 osi_Log0(afsd_logp, "Ioctl invalid state - dataout expected");
171 return CM_ERROR_INVAL;
177 /* called when we receive a write call. If this is the first write call after
178 * a series of reads (or the very first call), then we start a new call.
179 * We also ensure that things are properly initialized for the start of a call.
182 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
184 /* make sure the buffer(s) are allocated */
185 if (!ioctlp->ioctl.inAllocp)
186 ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
187 if (!ioctlp->ioctl.outAllocp)
188 ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
190 /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */
191 (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
192 (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
194 /* and make sure that we've reset our state for the new incoming request */
195 if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
196 ioctlp->ioctl.inCopied = 0;
197 ioctlp->ioctl.outCopied = 0;
198 ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
199 ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
200 ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
201 ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAOUT;
205 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
207 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
211 afs_int32 leftToCopy;
215 cm_user_t *userp = NULL;
220 count = smb_GetSMBParm(inp, 1);
222 /* Get the user and determine if it is the local machine account */
223 smbp = (smb_t *) inp;
224 uidp = smb_FindUID(vcp, smbp->uid, 0);
227 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
229 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
231 osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
232 uidp->userID, userp);
234 isSystem = smb_userIsLocalSystem(uidp);
235 userp = smb_GetUserFromUID(uidp);
237 osi_Log3(afsd_logp, "smb_IoctlRead uid %d user %x name %s",
239 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
241 osi_Log2(afsd_logp, "smb_IoctlRead uid %d user %x no name",
242 uidp->userID, userp);
244 smb_ReleaseUID(uidp);
246 osi_Log1(afsd_logp, "smb_IoctlRead no uid user %x no name", userp);
247 return CM_ERROR_BADSMB;
251 userp = cm_rootUserp;
256 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
258 cm_ReleaseUser(userp);
259 return CM_ERROR_NOSUCHPATH;
262 /* turn the connection around, if required */
263 code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
266 cm_ReleaseUser(userp);
270 leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
271 if (leftToCopy < 0) {
272 osi_Log0(afsd_logp, "smb_IoctlRead leftToCopy went negative");
273 cm_ReleaseUser(userp);
274 return CM_ERROR_INVAL;
276 if (count > leftToCopy)
279 /* now set the parms for a read of count bytes */
280 smb_SetSMBParm(outp, 0, count);
281 smb_SetSMBParm(outp, 1, 0);
282 smb_SetSMBParm(outp, 2, 0);
283 smb_SetSMBParm(outp, 3, 0);
284 smb_SetSMBParm(outp, 4, 0);
286 smb_SetSMBDataLength(outp, count+3);
288 op = smb_GetSMBData(outp, NULL);
290 *op++ = (char)(count & 0xff);
291 *op++ = (char)((count >> 8) & 0xff);
293 /* now copy the data into the response packet */
294 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
296 /* and adjust the counters */
297 iop->ioctl.outCopied += count;
299 cm_ReleaseUser(userp);
304 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
308 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
314 int inDataBlockCount;
317 count = smb_GetSMBParm(inp, 1);
320 smb_IoctlPrepareWrite(fidp, iop);
322 op = smb_GetSMBData(inp, NULL);
323 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
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, 0, count);
340 smb_SetSMBDataLength(outp, 0);
346 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
350 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
356 int inDataBlockCount;
359 count = smb_GetSMBParm(inp, 10);
362 smb_IoctlPrepareWrite(fidp, iop);
364 op = inp->data + smb_GetSMBParm(inp, 11);
365 inDataBlockCount = count;
367 if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
368 code = CM_ERROR_TOOBIG;
373 memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
376 iop->ioctl.inCopied += count;
379 /* return # of bytes written */
381 smb_SetSMBParm(outp, 2, count);
382 smb_SetSMBParm(outp, 3, 0); /* reserved */
383 smb_SetSMBParm(outp, 4, 0); /* reserved */
384 smb_SetSMBParm(outp, 5, 0); /* reserved */
385 smb_SetSMBDataLength(outp, 0);
392 /* called from V3 read to handle IOCTL descriptor reads */
394 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
397 unsigned short count;
406 count = smb_GetSMBParm(inp, 5);
408 /* Get the user and determine if it is the local machine account */
409 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
411 isSystem = smb_userIsLocalSystem(uidp);
412 userp = smb_GetUserFromUID(uidp);
414 osi_Log3(afsd_logp, "smb_IoctlV3Read uid %d user %x name %s",
416 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
418 osi_Log2(afsd_logp, "smb_IoctlV3Read uid %d user %x no name",
419 uidp->userID, userp);
422 osi_Log0(afsd_logp, "smb_IoctlV3Read no uid");
423 return CM_ERROR_BADSMB;
427 userp = cm_rootUserp;
433 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
436 smb_ReleaseUID(uidp);
437 cm_ReleaseUser(userp);
438 return CM_ERROR_NOSUCHPATH;
441 code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
444 smb_ReleaseUID(uidp);
447 cm_ReleaseUser(userp);
451 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
452 if (leftToCopy < 0) {
453 osi_Log0(afsd_logp, "smb_IoctlV3Read leftToCopy went negative");
454 cm_ReleaseUser(userp);
455 return CM_ERROR_INVAL;
457 if (count > leftToCopy)
458 count = (unsigned short)leftToCopy;
460 /* 0 and 1 are reserved for request chaining, were setup by our caller,
461 * and will be further filled in after we return.
463 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
464 smb_SetSMBParm(outp, 3, 0); /* resvd */
465 smb_SetSMBParm(outp, 4, 0); /* resvd */
466 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
467 /* fill in #6 when we have all the parameters' space reserved */
468 smb_SetSMBParm(outp, 7, 0); /* resv'd */
469 smb_SetSMBParm(outp, 8, 0); /* resv'd */
470 smb_SetSMBParm(outp, 9, 0); /* resv'd */
471 smb_SetSMBParm(outp, 10, 0); /* resv'd */
472 smb_SetSMBParm(outp, 11, 0); /* reserved */
474 /* get op ptr after putting in the last parm, since otherwise we don't
475 * know where the data really is.
477 op = smb_GetSMBData(outp, NULL);
479 /* now fill in offset from start of SMB header to first data byte (to op) */
480 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
482 /* set the packet data length the count of the # of bytes */
483 smb_SetSMBDataLength(outp, count);
485 /* now copy the data into the response packet */
486 memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
488 /* and adjust the counters */
489 iop->ioctl.outCopied += count;
491 /* and cleanup things */
492 cm_ReleaseUser(userp);
497 /* called from Read Raw to handle IOCTL descriptor reads */
499 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
512 /* Get the user and determine if it is the local machine account */
513 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
515 isSystem = smb_userIsLocalSystem(uidp);
516 userp = smb_GetUserFromUID(uidp);
518 osi_Log3(afsd_logp, "smb_IoctlRawRead uid %d user %x name %s",
520 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
522 osi_Log2(afsd_logp, "smb_IoctlRawRead uid %d user %x no name",
523 uidp->userID, userp);
525 smb_ReleaseUID(uidp);
527 osi_Log0(afsd_logp, "smb_IoctlRawRead no uid");
531 userp = cm_rootUserp;
535 code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
537 code = CM_ERROR_NOSUCHPATH;
541 code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
546 leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
547 if (leftToCopy < 0) {
548 osi_Log0(afsd_logp, "smb_IoctlReadRaw leftToCopy went negative");
549 code = CM_ERROR_INVAL;
554 memset(ncbp, 0, sizeof(NCB));
556 ncbp->ncb_length = (unsigned short) leftToCopy;
557 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
558 ncbp->ncb_command = NCBSEND;
559 /*ncbp->ncb_lana_num = smb_LANadapter;*/
560 ncbp->ncb_lana_num = vcp->lana;
562 ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
563 code = Netbios(ncbp);
566 osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
569 cm_ReleaseUser(userp);
574 /* parse the passed-in file name and do a namei on it. If we fail,
575 * return an error code, otherwise return the vnode located in *scpp.
577 #define CM_PARSE_FLAG_LITERAL 1
580 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
581 cm_scache_t **scpp, afs_uint32 flags)
584 cm_scache_t *substRootp = NULL;
585 cm_scache_t *iscp = NULL;
587 clientchar_t *relativePath = NULL;
588 clientchar_t *lastComponent = NULL;
589 afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
591 inPath = ioctlp->ioctl.inDatap;
592 /* setup the next data value for the caller to use */
593 ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
595 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
597 /* This is usually the file name, but for StatMountPoint it is the path. */
598 /* ioctlp->ioctl.inDatap can be either of the form:
601 * \\netbios-name\submount\path\.
602 * \\netbios-name\submount\path\file
605 /* We do not perform path name translation on the ioctl path data
606 * because these paths were not translated by Windows through the
607 * file system API. Therefore, they are not OEM characters but
608 * whatever the display character set is.
611 // TranslateExtendedChars(relativePath);
613 /* This is usually nothing, but for StatMountPoint it is the file name. */
614 // TranslateExtendedChars(ioctlp->ioctl.inDatap);
616 /* If the string starts with our UTF-8 prefix (which is the
617 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
618 strings), we assume that the provided path is UTF-8. Otherwise
619 we have to convert the string to UTF-8, since that is what we
620 want to use everywhere else.*/
622 if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
623 /* String is UTF-8 */
624 inPath += utf8_prefix_size;
625 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
627 relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
631 /* Not a UTF-8 string */
632 /* TODO: If this is an OEM string, we should convert it to
634 if (smb_StoreAnsiFilenames) {
635 cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
639 relativePath = malloc(cch * sizeof(clientchar_t));
640 cm_AnsiToClientString(inPath, -1, relativePath, cch);
642 TranslateExtendedChars(inPath);
644 cch = cm_OemToClientString(inPath, -1, NULL, 0);
648 relativePath = malloc(cch * sizeof(clientchar_t));
649 cm_OemToClientString(inPath, -1, relativePath, cch);
653 if (relativePath[0] == relativePath[1] &&
654 relativePath[1] == '\\' &&
655 !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
656 (int)cm_ClientStrLen(cm_NetbiosNameC)))
658 clientchar_t shareName[256];
659 clientchar_t *sharePath;
662 /* We may have found a UNC path.
663 * If the first component is the NetbiosName,
664 * then throw out the second component (the submount)
665 * since it had better expand into the value of ioctl->tidPathp
668 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1; /* buffer overflow vuln.? */
669 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
672 for (i = 0; *p && *p != '\\'; i++,p++ ) {
675 p++; /* skip past trailing slash */
676 shareName[i] = 0; /* terminate string */
678 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
680 /* we found a sharename, therefore use the resulting path */
681 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
682 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
683 userp, sharePath, reqp, &substRootp);
686 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
692 lastComponent = cm_ClientStrRChr(p, '\\');
693 if (lastComponent && (lastComponent - p) > 1 &&
694 cm_ClientStrLen(lastComponent) > 1) {
695 *lastComponent = '\0';
698 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
699 userp, NULL, reqp, &iscp);
701 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
702 userp, NULL, reqp, scpp);
704 cm_ReleaseSCache(iscp);
706 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
707 userp, NULL, reqp, scpp);
709 cm_ReleaseSCache(substRootp);
711 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
717 /* otherwise, treat the name as a cellname mounted off the afs root.
718 * This requires that we reconstruct the shareName string with
719 * leading and trailing slashes.
721 p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
722 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
726 for (i = 1; *p && *p != '\\'; i++,p++ ) {
729 p++; /* skip past trailing slash */
730 shareName[i++] = '/'; /* add trailing slash */
731 shareName[i] = 0; /* terminate string */
734 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
735 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
736 userp, shareName, reqp, &substRootp);
738 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
744 lastComponent = cm_ClientStrRChr(p, '\\');
745 if (lastComponent && (lastComponent - p) > 1 &&
746 cm_ClientStrLen(lastComponent) > 1) {
747 *lastComponent = '\0';
750 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
751 userp, NULL, reqp, &iscp);
753 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
754 userp, NULL, reqp, scpp);
756 cm_ReleaseSCache(iscp);
758 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
759 userp, NULL, reqp, scpp);
763 cm_ReleaseSCache(substRootp);
764 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
771 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
772 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
773 userp, ioctlp->tidPathp, reqp, &substRootp);
775 osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
781 lastComponent = cm_ClientStrRChr(relativePath, '\\');
782 if (lastComponent && (lastComponent - relativePath) > 1 &&
783 cm_ClientStrLen(lastComponent) > 1) {
784 *lastComponent = '\0';
787 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
788 userp, NULL, reqp, &iscp);
790 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
791 userp, NULL, reqp, scpp);
793 cm_ReleaseSCache(iscp);
795 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
796 userp, NULL, reqp, scpp);
799 cm_ReleaseSCache(substRootp);
800 osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
808 cm_ReleaseSCache(substRootp);
813 /* Ensure that the status object is up to date */
814 lock_ObtainWrite(&(*scpp)->rw);
815 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
816 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
818 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
819 lock_ReleaseWrite(&(*scpp)->rw);
821 /* and return success */
822 osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
828 #define LEAF_SIZE 256
829 /* parse the passed-in file name and do a namei on its parent. If we fail,
830 * return an error code, otherwise return the vnode located in *scpp.
833 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
834 cm_scache_t **scpp, clientchar_t *leafp)
837 clientchar_t tbuffer[1024];
838 clientchar_t *tp, *jp;
839 cm_scache_t *substRootp = NULL;
840 clientchar_t *inpathp = NULL;
843 inpathdatap = ioctlp->ioctl.inDatap;
845 /* If the string starts with our UTF-8 prefix (which is the
846 sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
847 strings), we assume that the provided path is UTF-8. Otherwise
848 we have to convert the string to UTF-8, since that is what we
849 want to use everywhere else.*/
851 if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
853 /* String is UTF-8 */
854 inpathdatap += utf8_prefix_size;
855 ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
857 inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
861 /* Not a UTF-8 string */
862 /* TODO: If this is an OEM string, we should convert it to
864 if (smb_StoreAnsiFilenames) {
865 cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
869 inpathp = malloc(cch * sizeof(clientchar_t));
870 cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
872 TranslateExtendedChars(inpathdatap);
874 cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
878 inpathp = malloc(cch * sizeof(clientchar_t));
879 cm_OemToClientString(inpathdatap, -1, inpathp, cch);
883 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
884 tp = cm_ClientStrRChr(tbuffer, '\\');
885 jp = cm_ClientStrRChr(tbuffer, '/');
888 else if (jp && (tp - tbuffer) < (jp - tbuffer))
891 cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
893 cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
898 cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
902 inpathp = NULL; /* We don't need this from this point on */
904 if (tbuffer[0] == tbuffer[1] &&
905 tbuffer[1] == '\\' &&
906 !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
907 (int)cm_ClientStrLen(cm_NetbiosNameC)))
909 clientchar_t shareName[256];
910 clientchar_t *sharePath;
913 /* We may have found a UNC path.
914 * If the first component is the NetbiosName,
915 * then throw out the second component (the submount)
916 * since it had better expand into the value of ioctl->tidPathp
919 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
920 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
923 for (i = 0; *p && *p != '\\'; i++,p++ ) {
926 p++; /* skip past trailing slash */
927 shareName[i] = 0; /* terminate string */
929 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
931 /* we found a sharename, therefore use the resulting path */
932 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
933 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
934 userp, sharePath, reqp, &substRootp);
936 if (code) return code;
938 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
939 userp, NULL, reqp, scpp);
940 cm_ReleaseSCache(substRootp);
941 if (code) return code;
943 /* otherwise, treat the name as a cellname mounted off the afs root.
944 * This requires that we reconstruct the shareName string with
945 * leading and trailing slashes.
947 p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
948 if ( !cm_ClientStrCmpNI(_C("all"), p, 3) )
952 for (i = 1; *p && *p != '\\'; i++,p++ ) {
955 p++; /* skip past trailing slash */
956 shareName[i++] = '/'; /* add trailing slash */
957 shareName[i] = 0; /* terminate string */
959 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
960 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
961 userp, shareName, reqp, &substRootp);
962 if (code) return code;
964 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
965 userp, NULL, reqp, scpp);
966 cm_ReleaseSCache(substRootp);
967 if (code) return code;
970 code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
971 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
972 userp, ioctlp->tidPathp, reqp, &substRootp);
973 if (code) return code;
975 code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
976 userp, NULL, reqp, scpp);
977 cm_ReleaseSCache(substRootp);
978 if (code) return code;
981 /* # of bytes of path */
982 code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
983 ioctlp->ioctl.inDatap += code;
985 /* Ensure that the status object is up to date */
986 lock_ObtainWrite(&(*scpp)->rw);
987 code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
988 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
990 cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
991 lock_ReleaseWrite(&(*scpp)->rw);
993 /* and return success */
998 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1005 struct ClearToken ct;
1011 int release_userp = 0;
1012 clientchar_t *uname = NULL;
1013 clientchar_t *smbname = NULL;
1014 clientchar_t *wdir = NULL;
1015 clientchar_t *rpc_sid = NULL;
1018 saveDataPtr = ioctlp->ioctl.inDatap;
1020 cm_SkipIoctlPath(&ioctlp->ioctl);
1022 tp = ioctlp->ioctl.inDatap;
1025 memcpy(&ticketLen, tp, sizeof(ticketLen));
1026 tp += sizeof(ticketLen);
1027 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1028 return CM_ERROR_INVAL;
1030 /* remember ticket and skip over it for now */
1034 /* clear token size */
1035 memcpy(&ctSize, tp, sizeof(ctSize));
1036 tp += sizeof(ctSize);
1037 if (ctSize != sizeof(struct ClearToken))
1038 return CM_ERROR_INVAL;
1041 memcpy(&ct, tp, ctSize);
1043 if (ct.AuthHandle == -1)
1044 ct.AuthHandle = 999; /* more rxvab compat stuff */
1046 /* more stuff, if any */
1047 if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
1048 /* flags: logon flag */
1049 memcpy(&flags, tp, sizeof(int));
1054 fschar_t * cellnamep;
1055 clientchar_t * temp;
1057 temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1058 cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
1059 cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
1065 code = CM_ERROR_NOSUCHCELL;
1068 tp += strlen(tp) + 1;
1071 uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1072 tp += strlen(tp) + 1;
1074 if (flags & PIOCTL_LOGON) {
1075 /* SMB user name with which to associate tokens */
1076 smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1077 osi_Log2(smb_logp,"smb_IoctlSetToken for user [%S] smbname [%S]",
1078 osi_LogSaveClientString(smb_logp,uname),
1079 osi_LogSaveClientString(smb_logp,smbname));
1080 fprintf(stderr, "SMB name = %S\n", smbname);
1081 tp += strlen(tp) + 1;
1083 osi_Log1(smb_logp,"smb_IoctlSetToken for user [%S]",
1084 osi_LogSaveClientString(smb_logp, uname));
1088 memcpy(&uuid, tp, sizeof(uuid));
1089 if (!cm_FindTokenEvent(uuid, sessionKey, &rpc_sid)) {
1090 code = CM_ERROR_INVAL;
1094 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && rpc_sid) {
1095 osi_Log1(smb_logp,"smb_IoctlSetToken Rpc Sid [%S]",
1096 osi_LogSaveClientString(smb_logp, rpc_sid));
1097 if (!cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, rpc_sid))
1098 pflags |= AFSCALL_FLAG_LOCAL_SYSTEM;
1101 if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1102 code = CM_ERROR_NOACCESS;
1106 cellp = cm_data.rootCellp;
1107 osi_Log0(smb_logp,"smb_IoctlSetToken - no name specified");
1110 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1112 DWORD dwSize1 = 0, dwSize2 = 0;
1113 wchar_t *pszRefDomain = NULL;
1114 SID_NAME_USE snu = SidTypeGroup;
1115 clientchar_t * secSidString = NULL;
1119 * The specified smbname is may not be a SID for the user.
1120 * See if we can obtain the SID for the specified name.
1121 * If we can, use that instead of the name provided.
1124 LookupAccountNameW( NULL /* System Name to begin Search */,
1129 gle = GetLastError();
1130 if (gle == ERROR_INSUFFICIENT_BUFFER) {
1131 pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1133 * Although dwSize2 is supposed to include the terminating
1134 * NUL character, on Win7 it does not.
1136 pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1139 if ( pSid && pszRefDomain ) {
1140 if (LookupAccountNameW( NULL /* System Name to begin Search */,
1143 pszRefDomain, &dwSize2,
1145 ConvertSidToStringSidW(pSid, &secSidString);
1149 userp = smb_FindCMUserBySID( secSidString, ioctlp->fidp->vcp->rname,
1150 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1151 LocalFree(secSidString);
1153 /* Free the SID so we can reuse the variable */
1160 * If the SID for the name could not be found,
1161 * perhaps it already is a SID
1163 if (!ConvertStringSidToSidW( smbname, &pSid)) {
1164 userp = smb_FindCMUserBySID( smbname, ioctlp->fidp->vcp->rname,
1165 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1167 userp = smb_FindCMUserByName( smbname, ioctlp->fidp->vcp->rname,
1168 SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1180 /* store the token */
1181 lock_ObtainMutex(&userp->mx);
1182 ucellp = cm_GetUCell(userp, cellp);
1183 osi_Log1(smb_logp,"smb_IoctlSetToken ucellp %lx", ucellp);
1184 ucellp->ticketLen = ticketLen;
1185 if (ucellp->ticketp)
1186 free(ucellp->ticketp); /* Discard old token if any */
1187 ucellp->ticketp = malloc(ticketLen);
1188 memcpy(ucellp->ticketp, ticket, ticketLen);
1190 * Get the session key from the RPC, rather than from the pioctl.
1193 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1195 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1196 ucellp->kvno = ct.AuthHandle;
1197 ucellp->expirationTime = ct.EndTimestamp;
1200 ucellp->uid = ANONYMOUSID;
1203 cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1205 cm_UsernameToId(uname, ucellp, &ucellp->uid);
1208 _InterlockedOr(&ucellp->flags, CM_UCELLFLAG_RXKAD);
1209 lock_ReleaseMutex(&userp->mx);
1211 if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1212 ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1215 cm_ResetACLCache(cellp, userp);
1218 SecureZeroMemory(sessionKey, sizeof(sessionKey));
1221 cm_ReleaseUser(userp);
1235 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1237 smb_user_t *uidp = ioctlp->uidp;
1239 if (uidp && uidp->unp) {
1242 cch = cm_ClientStringToUtf8(uidp->unp->name,
1244 ioctlp->ioctl.outDatap,
1245 (int)(SMB_IOCTL_MAXDATA -
1246 (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1247 / sizeof(cm_utf8char_t));
1249 ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1256 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1261 cm_ioctlQueryOptions_t *optionsp;
1262 afs_uint32 flags = 0;
1266 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1267 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1268 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1270 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1272 cm_SkipIoctlPath(&ioctlp->ioctl);
1273 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1274 optionsp->fid.vnode, optionsp->fid.unique);
1275 code = cm_GetSCache(&fid, &scp, userp, &req);
1277 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1283 code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1285 cm_ReleaseSCache(scp);
1290 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1295 afs_uint32 flags = 0;
1299 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1303 code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1305 cm_ReleaseSCache(scp);
1310 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1315 cm_ioctlQueryOptions_t *optionsp;
1316 afs_uint32 flags = 0;
1320 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1321 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1322 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1324 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1326 cm_SkipIoctlPath(&ioctlp->ioctl);
1327 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1328 optionsp->fid.vnode, optionsp->fid.unique);
1329 code = cm_GetSCache(&fid, &scp, userp, &req);
1331 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1336 code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1338 cm_ReleaseSCache(scp);
1344 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1350 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1352 return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1356 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1361 cm_ioctlQueryOptions_t *optionsp;
1362 afs_uint32 flags = 0;
1366 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1367 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1368 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1370 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1372 cm_SkipIoctlPath(&ioctlp->ioctl);
1373 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1374 optionsp->fid.vnode, optionsp->fid.unique);
1375 code = cm_GetSCache(&fid, &scp, userp, &req);
1377 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1382 code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1384 cm_ReleaseSCache(scp);
1390 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1395 cm_ioctlQueryOptions_t *optionsp;
1396 afs_uint32 flags = 0;
1400 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1401 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1402 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1404 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1406 cm_SkipIoctlPath(&ioctlp->ioctl);
1407 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1408 optionsp->fid.vnode, optionsp->fid.unique);
1409 code = cm_GetSCache(&fid, &scp, userp, &req);
1411 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1416 code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1418 cm_ReleaseSCache(scp);
1423 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1431 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1432 if (code) return code;
1434 code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1435 cm_ReleaseSCache(scp);
1441 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1445 cm_ioctlQueryOptions_t *optionsp;
1446 afs_uint32 flags = 0;
1451 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1452 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1453 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1455 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1457 cm_SkipIoctlPath(&ioctlp->ioctl);
1458 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1459 optionsp->fid.vnode, optionsp->fid.unique);
1460 code = cm_GetSCache(&fid, &scp, userp, &req);
1462 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1467 code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1469 cm_ReleaseSCache(scp);
1475 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1480 cm_ioctlQueryOptions_t * optionsp;
1481 afs_uint32 flags = 0;
1485 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1486 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1487 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1489 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1493 code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1495 cm_ReleaseSCache(scp);
1501 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1506 cm_ioctlQueryOptions_t * optionsp;
1507 afs_uint32 flags = 0;
1511 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1512 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1513 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1515 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1517 cm_SkipIoctlPath(&ioctlp->ioctl);
1518 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1519 optionsp->fid.vnode, optionsp->fid.unique);
1520 code = cm_GetSCache(&fid, &scp, userp, &req);
1522 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1527 code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1529 cm_ReleaseSCache(scp);
1535 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1540 cm_ioctlQueryOptions_t *optionsp;
1541 afs_uint32 flags = 0;
1545 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1546 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1547 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1549 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1551 cm_SkipIoctlPath(&ioctlp->ioctl);
1552 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1553 optionsp->fid.vnode, optionsp->fid.unique);
1554 code = cm_GetSCache(&fid, &scp, userp, &req);
1556 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1561 code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1563 cm_ReleaseSCache(scp);
1569 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1574 cm_ioctlQueryOptions_t *optionsp;
1575 afs_uint32 flags = 0;
1579 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1580 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1581 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1583 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1585 cm_SkipIoctlPath(&ioctlp->ioctl);
1586 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1587 optionsp->fid.vnode, optionsp->fid.unique);
1588 code = cm_GetSCache(&fid, &scp, userp, &req);
1590 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1595 code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1597 cm_ReleaseSCache(scp);
1604 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1612 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1616 code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1618 cm_ReleaseSCache(dscp);
1624 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1632 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1636 code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1638 cm_ReleaseSCache(dscp);
1644 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1646 cm_SkipIoctlPath(&ioctlp->ioctl); /* we don't care about the path */
1648 return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1652 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1654 /* we don't print anything superfluous, so we don't support the gag call */
1655 return CM_ERROR_INVAL;
1659 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1661 cm_SkipIoctlPath(&ioctlp->ioctl);
1663 return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1666 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1668 cm_SkipIoctlPath(&ioctlp->ioctl);
1670 return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1675 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1677 cm_SkipIoctlPath(&ioctlp->ioctl);
1679 return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1683 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1685 cm_SkipIoctlPath(&ioctlp->ioctl);
1687 return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1691 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1693 cm_SkipIoctlPath(&ioctlp->ioctl);
1695 return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1699 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1701 cm_SkipIoctlPath(&ioctlp->ioctl);
1703 return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1707 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1709 cm_SkipIoctlPath(&ioctlp->ioctl);
1711 return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1715 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1717 cm_SkipIoctlPath(&ioctlp->ioctl);
1719 return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1723 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1725 cm_SkipIoctlPath(&ioctlp->ioctl);
1727 return cm_IoctlSysName(&ioctlp->ioctl, userp);
1731 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1733 cm_SkipIoctlPath(&ioctlp->ioctl);
1735 return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1739 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1741 cm_SkipIoctlPath(&ioctlp->ioctl);
1743 return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1747 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1749 cm_SkipIoctlPath(&ioctlp->ioctl);
1751 return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1755 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1757 cm_SkipIoctlPath(&ioctlp->ioctl);
1759 return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1763 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1765 /* we ignore default asynchrony since we only have one way
1766 * of doing this today.
1772 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1776 clientchar_t leaf[LEAF_SIZE];
1781 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1785 code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1787 cm_ReleaseSCache(dscp);
1792 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1796 clientchar_t leaf[LEAF_SIZE];
1801 code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1802 if (code) return code;
1804 code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1806 cm_ReleaseSCache(dscp);
1812 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1820 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1821 if (code) return code;
1823 code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1825 cm_ReleaseSCache(dscp);
1830 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1831 {/*CHECK FOR VALID SYMLINK*/
1838 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1839 if (code) return code;
1841 code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1843 cm_ReleaseSCache(dscp);
1849 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1857 code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1858 if (code) return code;
1860 code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1862 cm_ReleaseSCache(dscp);
1868 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1870 cm_SkipIoctlPath(&ioctlp->ioctl);
1872 return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1876 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1878 cm_SkipIoctlPath(&ioctlp->ioctl);
1880 return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1885 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1887 cm_SkipIoctlPath(&ioctlp->ioctl);
1889 return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1894 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1896 cm_SkipIoctlPath(&ioctlp->ioctl);
1898 return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1903 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1905 cm_SkipIoctlPath(&ioctlp->ioctl);
1907 return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1911 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1913 cm_SkipIoctlPath(&ioctlp->ioctl);
1915 return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1919 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1921 cm_SkipIoctlPath(&ioctlp->ioctl);
1923 return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1927 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1929 cm_SkipIoctlPath(&ioctlp->ioctl);
1931 return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1936 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1938 cm_SkipIoctlPath(&ioctlp->ioctl);
1940 return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1944 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1946 cm_SkipIoctlPath(&ioctlp->ioctl);
1948 return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1952 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1954 cm_SkipIoctlPath(&ioctlp->ioctl);
1956 return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1961 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1963 cm_SkipIoctlPath(&ioctlp->ioctl);
1965 return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1969 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1974 cm_ioctlQueryOptions_t *optionsp;
1975 afs_uint32 flags = 0;
1979 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1980 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1981 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1983 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1985 cm_SkipIoctlPath(&ioctlp->ioctl);
1986 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1987 optionsp->fid.vnode, optionsp->fid.unique);
1988 code = cm_GetSCache(&fid, &scp, userp, &req);
1990 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1995 code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1996 cm_ReleaseSCache(scp);
2001 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2007 cm_SkipIoctlPath(&ioctlp->ioctl);
2009 return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
2015 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2019 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2024 cm_ioctlQueryOptions_t *optionsp;
2025 afs_uint32 flags = 0;
2029 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2031 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2032 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2034 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2036 cm_SkipIoctlPath(&ioctlp->ioctl);
2037 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2038 optionsp->fid.vnode, optionsp->fid.unique);
2039 code = cm_GetSCache(&fid, &scp, userp, &req);
2041 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2046 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2049 code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
2051 cm_ReleaseSCache(scp);
2059 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2063 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2068 cm_ioctlQueryOptions_t *optionsp;
2069 afs_uint32 flags = 0;
2073 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2075 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2076 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2078 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2080 cm_SkipIoctlPath(&ioctlp->ioctl);
2081 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2082 optionsp->fid.vnode, optionsp->fid.unique);
2083 code = cm_GetSCache(&fid, &scp, userp, &req);
2085 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2090 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2093 code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
2095 cm_ReleaseSCache(scp);
2102 smb_IoctlGetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2107 cm_ioctlQueryOptions_t *optionsp;
2108 afs_uint32 flags = 0;
2112 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2113 if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2114 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2116 if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2118 cm_SkipIoctlPath(&ioctlp->ioctl);
2119 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2120 optionsp->fid.vnode, optionsp->fid.unique);
2121 code = cm_GetSCache(&fid, &scp, userp, &req);
2123 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2128 code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2130 cm_ReleaseSCache(scp);
2139 * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2142 smb_IoctlSetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2147 cm_ioctlQueryOptions_t *optionsp;
2148 afs_uint32 flags = 0;
2152 optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2154 if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2155 flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2157 if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2159 cm_SkipIoctlPath(&ioctlp->ioctl);
2160 cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2161 optionsp->fid.vnode, optionsp->fid.unique);
2162 code = cm_GetSCache(&fid, &scp, userp, &req);
2164 code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2169 cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2172 code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2174 cm_ReleaseSCache(scp);