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>
26 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
28 void smb_InitIoctl(void)
30 smb_ioctlProcsp[VIOCGETAL] = cm_IoctlGetACL;
31 smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = cm_IoctlGetFileCellName;
32 smb_ioctlProcsp[VIOCSETAL] = cm_IoctlSetACL;
33 smb_ioctlProcsp[VIOC_FLUSHVOLUME] = cm_IoctlFlushVolume;
34 smb_ioctlProcsp[VIOCFLUSH] = cm_IoctlFlushFile;
35 smb_ioctlProcsp[VIOCSETVOLSTAT] = cm_IoctlSetVolumeStatus;
36 smb_ioctlProcsp[VIOCGETVOLSTAT] = cm_IoctlGetVolumeStatus;
37 smb_ioctlProcsp[VIOCWHEREIS] = cm_IoctlWhereIs;
38 smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = cm_IoctlStatMountPoint;
39 smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = cm_IoctlDeleteMountPoint;
40 smb_ioctlProcsp[VIOCCKSERV] = cm_IoctlCheckServers;
41 smb_ioctlProcsp[VIOC_GAG] = cm_IoctlGag;
42 smb_ioctlProcsp[VIOCCKBACK] = cm_IoctlCheckVolumes;
43 smb_ioctlProcsp[VIOCSETCACHESIZE] = cm_IoctlSetCacheSize;
44 smb_ioctlProcsp[VIOCGETCACHEPARMS] = cm_IoctlGetCacheParms;
45 smb_ioctlProcsp[VIOCGETCELL] = cm_IoctlGetCell;
46 smb_ioctlProcsp[VIOCNEWCELL] = cm_IoctlNewCell;
47 smb_ioctlProcsp[VIOC_GET_WS_CELL] = cm_IoctlGetWsCell;
48 smb_ioctlProcsp[VIOC_AFS_SYSNAME] = cm_IoctlSysName;
49 smb_ioctlProcsp[VIOC_GETCELLSTATUS] = cm_IoctlGetCellStatus;
50 smb_ioctlProcsp[VIOC_SETCELLSTATUS] = cm_IoctlSetCellStatus;
51 smb_ioctlProcsp[VIOC_SETSPREFS] = cm_IoctlSetSPrefs;
52 smb_ioctlProcsp[VIOC_GETSPREFS] = cm_IoctlGetSPrefs;
53 smb_ioctlProcsp[VIOC_STOREBEHIND] = cm_IoctlStoreBehind;
54 smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = cm_IoctlCreateMountPoint;
55 smb_ioctlProcsp[VIOC_TRACECTL] = cm_IoctlTraceControl;
56 smb_ioctlProcsp[VIOCSETTOK] = cm_IoctlSetToken;
57 smb_ioctlProcsp[VIOCGETTOK] = cm_IoctlGetTokenIter;
58 smb_ioctlProcsp[VIOCNEWGETTOK] = cm_IoctlGetToken;
59 smb_ioctlProcsp[VIOCDELTOK] = cm_IoctlDelToken;
60 smb_ioctlProcsp[VIOCDELALLTOK] = cm_IoctlDelAllToken;
61 smb_ioctlProcsp[VIOC_SYMLINK] = cm_IoctlSymlink;
62 smb_ioctlProcsp[VIOC_LISTSYMLINK] = cm_IoctlListlink;
63 smb_ioctlProcsp[VIOC_DELSYMLINK] = cm_IoctlDeletelink;
64 smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = cm_IoctlMakeSubmount;
65 smb_ioctlProcsp[VIOC_GETRXKCRYPT] = cm_IoctlGetRxkcrypt;
66 smb_ioctlProcsp[VIOC_SETRXKCRYPT] = cm_IoctlSetRxkcrypt;
69 /* called to make a fid structure into an IOCTL fid structure */
70 void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
73 cm_space_t *copyPrefix;
75 lock_ObtainMutex(&fidp->mx);
76 fidp->flags |= SMB_FID_IOCTL;
77 fidp->scp = &cm_fakeSCache;
78 if (fidp->ioctlp == NULL) {
79 iop = malloc(sizeof(*iop));
80 memset(iop, 0, sizeof(*iop));
84 copyPrefix = cm_GetSpace();
85 strcpy(copyPrefix->data, prefix->data);
86 fidp->ioctlp->prefix = copyPrefix;
88 lock_ReleaseMutex(&fidp->mx);
91 /* called when we receive a read call, does the send of the received data if
92 * this is the first read call. This is the function that actually makes the
93 * call to the ioctl code.
95 smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
98 smb_ioctlProc_t *procp;
101 if (ioctlp->flags & SMB_IOCTLFLAG_DATAIN) {
102 ioctlp->flags &= ~SMB_IOCTLFLAG_DATAIN;
104 /* do the call now, or fail if we didn't get an opcode, or
105 * enough of an opcode.
107 if (ioctlp->inCopied < sizeof(long)) return CM_ERROR_INVAL;
108 memcpy(&opcode, ioctlp->inDatap, sizeof(long));
109 ioctlp->inDatap += sizeof(long);
111 osi_Log1(afsd_logp, "Ioctl opcode %d", opcode);
113 /* check for opcode out of bounds */
114 if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS)
115 return CM_ERROR_TOOBIG;
117 /* check for no such proc */
118 procp = smb_ioctlProcsp[opcode];
119 if (procp == NULL) return CM_ERROR_BADOP;
121 /* otherwise, make the call */
122 ioctlp->outDatap += sizeof(long); /* reserve room for return code */
123 code = (*procp)(ioctlp, userp);
125 osi_Log1(afsd_logp, "Ioctl return code %d", code);
127 /* copy in return code */
128 memcpy(ioctlp->outAllocp, &code, sizeof(long));
133 /* called when we receive a write call. If this is the first write call after
134 * a series of reads (or the very first call), then we start a new call.
135 * We also ensure that things are properly initialized for the start of a call.
137 void smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
139 /* make sure the buffer(s) are allocated */
140 if (!ioctlp->inAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA);
141 if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA);
143 /* and make sure that we've reset our state for the new incoming request */
144 if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) {
145 ioctlp->inCopied = 0;
146 ioctlp->outCopied = 0;
147 ioctlp->inDatap = ioctlp->inAllocp;
148 ioctlp->outDatap = ioctlp->outAllocp;
149 ioctlp->flags |= SMB_IOCTLFLAG_DATAIN;
153 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
154 long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
165 count = smb_GetSMBParm(inp, 1);
166 userp = smb_GetUser(vcp, inp);
169 iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
171 /* turn the connection around, if required */
172 code = smb_IoctlPrepareRead(fidp, iop, userp);
175 cm_ReleaseUser(userp);
179 if (iop->flags & SMB_IOCTLFLAG_LOGON) {
180 vcp->logonDLLUser = userp;
181 userp->flags |= CM_USERFLAG_WASLOGON;
184 leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
185 if (count > leftToCopy) count = leftToCopy;
187 /* now set the parms for a read of count bytes */
188 smb_SetSMBParm(outp, 0, count);
189 smb_SetSMBParm(outp, 1, 0);
190 smb_SetSMBParm(outp, 2, 0);
191 smb_SetSMBParm(outp, 3, 0);
192 smb_SetSMBParm(outp, 4, 0);
194 smb_SetSMBDataLength(outp, count+3);
196 op = smb_GetSMBData(outp, NULL);
198 *op++ = count & 0xff;
199 *op++ = (count >> 8) & 0xff;
201 /* now copy the data into the response packet */
202 memcpy(op, iop->outCopied + iop->outAllocp, count);
204 /* and adjust the counters */
205 iop->outCopied += count;
207 cm_ReleaseUser(userp);
208 smb_ReleaseFID(fidp);
213 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
216 long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
222 long inDataBlockCount;
225 count = smb_GetSMBParm(inp, 1);
228 smb_IoctlPrepareWrite(fidp, iop);
230 op = smb_GetSMBData(inp, NULL);
231 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
233 if (count + iop->inCopied > SMB_IOCTL_MAXDATA) {
234 code = CM_ERROR_TOOBIG;
239 memcpy(iop->inDatap + iop->inCopied, op, count);
242 iop->inCopied += count;
245 /* return # of bytes written */
247 smb_SetSMBParm(outp, 0, count);
248 smb_SetSMBDataLength(outp, 0);
251 smb_ReleaseFID(fidp);
255 /* called from V3 read to handle IOCTL descriptor reads */
256 long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
266 count = smb_GetSMBParm(inp, 5);
268 userp = smb_GetUser(vcp, inp);
273 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
274 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
276 osi_LogSaveString(afsd_logp, uidp->name));
277 smb_ReleaseUID(uidp);
280 iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
282 code = smb_IoctlPrepareRead(fidp, iop, userp);
284 cm_ReleaseUser(userp);
285 smb_ReleaseFID(fidp);
289 if (iop->flags & SMB_IOCTLFLAG_LOGON) {
290 vcp->logonDLLUser = userp;
291 userp->flags |= CM_USERFLAG_WASLOGON;
294 leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
295 if (count > leftToCopy) count = leftToCopy;
297 /* 0 and 1 are reserved for request chaining, were setup by our caller,
298 * and will be further filled in after we return.
300 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
301 smb_SetSMBParm(outp, 3, 0); /* resvd */
302 smb_SetSMBParm(outp, 4, 0); /* resvd */
303 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
304 /* fill in #6 when we have all the parameters' space reserved */
305 smb_SetSMBParm(outp, 7, 0); /* resv'd */
306 smb_SetSMBParm(outp, 8, 0); /* resv'd */
307 smb_SetSMBParm(outp, 9, 0); /* resv'd */
308 smb_SetSMBParm(outp, 10, 0); /* resv'd */
309 smb_SetSMBParm(outp, 11, 0); /* reserved */
311 /* get op ptr after putting in the last parm, since otherwise we don't
312 * know where the data really is.
314 op = smb_GetSMBData(outp, NULL);
316 /* now fill in offset from start of SMB header to first data byte (to op) */
317 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
319 /* set the packet data length the count of the # of bytes */
320 smb_SetSMBDataLength(outp, count);
322 /* now copy the data into the response packet */
323 memcpy(op, iop->outCopied + iop->outAllocp, count);
325 /* and adjust the counters */
326 iop->outCopied += count;
328 /* and cleanup things */
329 cm_ReleaseUser(userp);
330 smb_ReleaseFID(fidp);
335 /* called from Read Raw to handle IOCTL descriptor reads */
336 long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
347 userp = smb_GetUser(vcp, inp);
352 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
353 osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
355 osi_LogSaveString(afsd_logp, uidp->name));
356 smb_ReleaseUID(uidp);
359 iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
361 code = smb_IoctlPrepareRead(fidp, iop, userp);
363 cm_ReleaseUser(userp);
364 smb_ReleaseFID(fidp);
368 if (iop->flags & SMB_IOCTLFLAG_LOGON) {
369 vcp->logonDLLUser = userp;
370 userp->flags |= CM_USERFLAG_WASLOGON;
373 leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
376 memset((char *)ncbp, 0, sizeof(NCB));
378 ncbp->ncb_length = (unsigned short) leftToCopy;
379 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
380 ncbp->ncb_command = NCBSEND;
381 ncbp->ncb_buffer = iop->outCopied + iop->outAllocp;
383 code = Netbios(ncbp);
385 osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
387 cm_ReleaseUser(userp);
388 smb_ReleaseFID(fidp);