windows-cm_ioctl_query_opts-20080115
[openafs.git] / src / WINNT / afsd / smb_ioctl.c
index a5d36df..7f3715e 100644 (file)
@@ -10,9 +10,7 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifndef DJGPP
 #include <windows.h>
-#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
 
 /*extern unsigned char smb_LANadapter;*/
-extern LANA_ENUM lana_list;
 
 void smb_InitIoctl(void)
 {
+        int i;
+        for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
+           smb_ioctlProcsp[i] = NULL;
+
        smb_ioctlProcsp[VIOCGETAL] = cm_IoctlGetACL;
         smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = cm_IoctlGetFileCellName;
         smb_ioctlProcsp[VIOCSETAL] = cm_IoctlSetACL;
@@ -69,74 +70,86 @@ void smb_InitIoctl(void)
        smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = cm_IoctlMakeSubmount;
        smb_ioctlProcsp[VIOC_GETRXKCRYPT] = cm_IoctlGetRxkcrypt;
        smb_ioctlProcsp[VIOC_SETRXKCRYPT] = cm_IoctlSetRxkcrypt;
-#ifdef DJGPP
-       smb_ioctlProcsp[VIOC_SHUTDOWN] = cm_IoctlShutdown;
-#endif
+       smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
+       smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = cm_IoctlMemoryDump;
+       smb_ioctlProcsp[VIOC_ISSYMLINK] = cm_IoctlIslink;
+        smb_ioctlProcsp[VIOC_FLUSHALL] = cm_IoctlFlushAllVolumes;
+        smb_ioctlProcsp[VIOCGETFID] = cm_IoctlGetFid;
+        smb_ioctlProcsp[VIOCGETOWNER] = cm_IoctlGetOwner;
+        smb_ioctlProcsp[VIOC_RXSTAT_PROC] = cm_IoctlRxStatProcess;
+        smb_ioctlProcsp[VIOC_RXSTAT_PEER] = cm_IoctlRxStatPeer;
+        smb_ioctlProcsp[VIOC_UUIDCTL] = cm_IoctlUUIDControl;
+        smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = cm_IoctlPathAvailability;
+        smb_ioctlProcsp[VIOC_GETFILETYPE] = cm_IoctlGetFileType;
+        smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = cm_IoctlVolStatTest;
 }
 
 /* called to make a fid structure into an IOCTL fid structure */
 void smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
 {
-       smb_ioctl_t *iop;
-       cm_space_t *copyPrefix;
-
-       lock_ObtainMutex(&fidp->mx);
-       fidp->flags |= SMB_FID_IOCTL;
-       fidp->scp = &cm_fakeSCache;
-        if (fidp->ioctlp == NULL) {
-               iop = malloc(sizeof(*iop));
-                memset(iop, 0, sizeof(*iop));
-                fidp->ioctlp = iop;
-                               iop->fidp = fidp;
-        }
-       if (prefix) {
-               copyPrefix = cm_GetSpace();
-               strcpy(copyPrefix->data, prefix->data);
-               fidp->ioctlp->prefix = copyPrefix;
-       }
-       lock_ReleaseMutex(&fidp->mx);
+    smb_ioctl_t *iop;
+    cm_space_t *copyPrefix;
+
+    lock_ObtainMutex(&fidp->mx);
+    fidp->flags |= SMB_FID_IOCTL;
+    fidp->scp = &cm_data.fakeSCache;
+    cm_HoldSCache(fidp->scp);
+    if (fidp->ioctlp == NULL) {
+        iop = malloc(sizeof(*iop));
+        memset(iop, 0, sizeof(*iop));
+        fidp->ioctlp = iop;
+        iop->fidp = fidp;
+    }
+    if (prefix) {
+        copyPrefix = cm_GetSpace();
+        strcpy(copyPrefix->data, prefix->data);
+        fidp->ioctlp->prefix = copyPrefix;
+    }
+    lock_ReleaseMutex(&fidp->mx);
 }
 
 /* called when we receive a read call, does the send of the received data if
  * this is the first read call.  This is the function that actually makes the
  * call to the ioctl code.
  */
-smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
+long smb_IoctlPrepareRead(smb_fid_t *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp)
 {
-       long opcode;
-        smb_ioctlProc_t *procp;
-        long code;
+    long opcode;
+    smb_ioctlProc_t *procp = NULL;
+    long code;
 
-       if (ioctlp->flags & SMB_IOCTLFLAG_DATAIN) {
-               ioctlp->flags &= ~SMB_IOCTLFLAG_DATAIN;
-                
-                /* do the call now, or fail if we didn't get an opcode, or
-                 * enough of an opcode.
-                 */
-                if (ioctlp->inCopied < sizeof(long)) return CM_ERROR_INVAL;
-                memcpy(&opcode, ioctlp->inDatap, sizeof(long));
-                ioctlp->inDatap += sizeof(long);
-
-                osi_Log1(afsd_logp, "Ioctl opcode %d", opcode);
-
-               /* check for opcode out of bounds */
-                if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS)
-                       return CM_ERROR_TOOBIG;
-               
-                /* check for no such proc */
-                procp = smb_ioctlProcsp[opcode];
-                if (procp == NULL) return CM_ERROR_BADOP;
-
-               /* otherwise, make the call */
-               ioctlp->outDatap += sizeof(long);       /* reserve room for return code */
-                code = (*procp)(ioctlp, userp);
-
-               osi_Log1(afsd_logp, "Ioctl return code %d", code);
-
-               /* copy in return code */
-                memcpy(ioctlp->outAllocp, &code, sizeof(long));
-        }
-        return 0;
+    if (ioctlp->flags & SMB_IOCTLFLAG_DATAIN) {
+        ioctlp->flags &= ~SMB_IOCTLFLAG_DATAIN;
+
+        /* do the call now, or fail if we didn't get an opcode, or
+         * enough of an opcode.
+         */
+        if (ioctlp->inCopied < sizeof(long)) 
+            return CM_ERROR_INVAL;
+        memcpy(&opcode, ioctlp->inDatap, sizeof(long));
+        ioctlp->inDatap += sizeof(long);
+
+        osi_Log1(afsd_logp, "Ioctl opcode 0x%x", opcode);
+
+        /* check for opcode out of bounds */
+        if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS)
+            return CM_ERROR_TOOBIG;
+
+        /* check for no such proc */
+       procp = smb_ioctlProcsp[opcode];
+        if (procp == NULL) 
+            return CM_ERROR_BADOP;
+
+        /* otherwise, make the call */
+        ioctlp->outDatap += sizeof(long);      /* reserve room for return code */
+        code = (*procp)(ioctlp, userp);
+
+        osi_Log1(afsd_logp, "Ioctl return code 0x%x", code);
+
+        /* copy in return code */
+        memcpy(ioctlp->outAllocp, &code, sizeof(long));
+    }
+    return 0;
 }
 
 /* called when we receive a write call.  If this is the first write call after
@@ -176,10 +189,14 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
 
         iop = fidp->ioctlp;
         count = smb_GetSMBParm(inp, 1);
-        userp = smb_GetUser(vcp, inp);
+        userp = smb_GetUserFromVCP(vcp, inp);
 
        /* Identify tree */
-       iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
 
        /* turn the connection around, if required */
        code = smb_IoctlPrepareRead(fidp, iop, userp);
@@ -189,7 +206,7 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
                return code;
         }
 
-       leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
+       leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied);
         if (count > leftToCopy) count = leftToCopy;
         
         /* now set the parms for a read of count bytes */
@@ -203,8 +220,8 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
 
         op = smb_GetSMBData(outp, NULL);
         *op++ = 1;
-        *op++ = count & 0xff;
-        *op++ = (count >> 8) & 0xff;
+        *op++ = (char)(count & 0xff);
+        *op++ = (char)((count >> 8) & 0xff);
         
        /* now copy the data into the response packet */
         memcpy(op, iop->outCopied + iop->outAllocp, count);
@@ -213,7 +230,6 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
         iop->outCopied += count;
         
         cm_ReleaseUser(userp);
-        smb_ReleaseFID(fidp);
 
         return 0;
 }
@@ -256,170 +272,208 @@ done:
                 smb_SetSMBDataLength(outp, 0);
         }
 
-        smb_ReleaseFID(fidp);
         return code;
 }
 
-/* called from V3 read to handle IOCTL descriptor reads */
-long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+/* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
+ * file descriptor.
+ */
+long smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        smb_ioctl_t *iop;
         long count;
         long code;
-        long leftToCopy;
         char *op;
-        cm_user_t *userp;
+        int inDataBlockCount;
 
+       code = 0;
+       count = smb_GetSMBParm(inp, 10);
         iop = fidp->ioctlp;
-        count = smb_GetSMBParm(inp, 5);
-       
-       userp = smb_GetUser(vcp, inp);
-
-       {
-               smb_user_t *uidp;
-
-               uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-               if (uidp && uidp->unp)
-                   osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
-                            uidp->userID, userp,
-                            osi_LogSaveString(afsd_logp, uidp->unp->name));
-               else {
-                       if (uidp)
-                   osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
-                            uidp->userID, userp);
-                       else
-                   osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
-                            userp);
-               }
-               smb_ReleaseUID(uidp);
-       }
+        
+       smb_IoctlPrepareWrite(fidp, iop);
 
-       iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+        op = inp->data + smb_GetSMBParm(inp, 11);
+        inDataBlockCount = count;
+       
+        if (count + iop->inCopied > SMB_IOCTL_MAXDATA) {
+               code = CM_ERROR_TOOBIG;
+                goto done;
+        }
+        
+       /* copy data */
+        memcpy(iop->inDatap + iop->inCopied, op, count);
+        
+        /* adjust counts */
+        iop->inCopied += count;
 
-       code = smb_IoctlPrepareRead(fidp, iop, userp);
-        if (code) {
-               cm_ReleaseUser(userp);
-                smb_ReleaseFID(fidp);
-               return code;
+done:
+       /* return # of bytes written */
+       if (code == 0) {
+               smb_SetSMBParm(outp, 2, count);
+                smb_SetSMBParm(outp, 3, 0); /* reserved */
+               smb_SetSMBParm(outp, 4, 0); /* reserved */
+               smb_SetSMBParm(outp, 5, 0); /* reserved */
+               smb_SetSMBDataLength(outp, 0);
         }
 
-       leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
-        if (count > leftToCopy) count = leftToCopy;
+        return code;
+}
+
+
+/* called from V3 read to handle IOCTL descriptor reads */
+long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+    smb_ioctl_t *iop;
+    long count;
+    long code;
+    long leftToCopy;
+    char *op;
+    cm_user_t *userp;
+    smb_user_t *uidp;
+
+    iop = fidp->ioctlp;
+    count = smb_GetSMBParm(inp, 5);
+       
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    userp = smb_GetUserFromUID(uidp);
+    osi_assertx(userp != NULL, "null cm_user_t");
+    iop->uidp = uidp;
+    if (uidp && uidp->unp) {
+        osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
+                  uidp->userID, userp,
+                  osi_LogSaveString(afsd_logp, uidp->unp->name));
+    } else {
+        if (uidp)
+           osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
+                     uidp->userID, userp);
+        else
+           osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
+                    userp);
+    }
+
+    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
+    if (code) {
+       if (uidp)
+           smb_ReleaseUID(uidp);
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
+
+    code = smb_IoctlPrepareRead(fidp, iop, userp);
+    if (uidp) {
+        iop->uidp = 0;
+        smb_ReleaseUID(uidp);
+    }
+    if (code) {
+       cm_ReleaseUser(userp);
+       return code;
+    }
+
+    leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied);
+    if (count > leftToCopy) count = leftToCopy;
         
-       /* 0 and 1 are reserved for request chaining, were setup by our caller,
-         * and will be further filled in after we return.
-         */
-        smb_SetSMBParm(outp, 2, 0);    /* remaining bytes, for pipes */
-        smb_SetSMBParm(outp, 3, 0);    /* resvd */
-        smb_SetSMBParm(outp, 4, 0);    /* resvd */
-       smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
-        /* fill in #6 when we have all the parameters' space reserved */
-        smb_SetSMBParm(outp, 7, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 8, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 9, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 10, 0);   /* resv'd */
-       smb_SetSMBParm(outp, 11, 0);    /* reserved */
-
-       /* get op ptr after putting in the last parm, since otherwise we don't
-         * know where the data really is.
-         */
-        op = smb_GetSMBData(outp, NULL);
+    /* 0 and 1 are reserved for request chaining, were setup by our caller,
+     * and will be further filled in after we return.
+     */
+    smb_SetSMBParm(outp, 2, 0);        /* remaining bytes, for pipes */
+    smb_SetSMBParm(outp, 3, 0);        /* resvd */
+    smb_SetSMBParm(outp, 4, 0);        /* resvd */
+    smb_SetSMBParm(outp, 5, count);    /* # of bytes we're going to read */
+    /* fill in #6 when we have all the parameters' space reserved */
+    smb_SetSMBParm(outp, 7, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 8, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 9, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 10, 0);       /* resv'd */
+    smb_SetSMBParm(outp, 11, 0);       /* reserved */
+
+    /* get op ptr after putting in the last parm, since otherwise we don't
+     * know where the data really is.
+     */
+    op = smb_GetSMBData(outp, NULL);
         
-        /* now fill in offset from start of SMB header to first data byte (to op) */
-        smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
+    /* now fill in offset from start of SMB header to first data byte (to op) */
+    smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
 
-       /* set the packet data length the count of the # of bytes */
-        smb_SetSMBDataLength(outp, count);
+    /* set the packet data length the count of the # of bytes */
+    smb_SetSMBDataLength(outp, count);
         
-       /* now copy the data into the response packet */
-        memcpy(op, iop->outCopied + iop->outAllocp, count);
+    /* now copy the data into the response packet */
+    memcpy(op, iop->outCopied + iop->outAllocp, count);
 
-        /* and adjust the counters */
-        iop->outCopied += count;
-        
-        /* and cleanup things */
-        cm_ReleaseUser(userp);
-        smb_ReleaseFID(fidp);
+    /* and adjust the counters */
+    iop->outCopied += count;
 
-        return 0;
-}
+    /* and cleanup things */
+    cm_ReleaseUser(userp);
+
+    return 0;
+}      
 
 /* called from Read Raw to handle IOCTL descriptor reads */
 long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
-       smb_packet_t *outp
-#ifdef DJGPP
-, dos_ptr rawBuf
-#endif /* DJGPP */
-)
+                     smb_packet_t *outp
+                     )
 {
-       smb_ioctl_t *iop;
-       long leftToCopy;
-       NCB *ncbp;
-       long code;
-       cm_user_t *userp;
-#ifdef DJGPP
-        dos_ptr dos_ncb;
-
-        if (rawBuf == 0)
-        {
-                osi_Log0(afsd_logp, "Failed to get raw buf for smb_IoctlReadRaw");
-                return -1;
-        }
-#endif /* DJGPP */
-
-       iop = fidp->ioctlp;
-
-       userp = smb_GetUser(vcp, inp);
-
-       {
-               smb_user_t *uidp;
-
-               uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-               if (uidp && uidp->unp)
-                   osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
-                            uidp->userID, userp,
-                            osi_LogSaveString(afsd_logp, uidp->unp->name));
-               else
-                   osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
-                            uidp->userID, userp);
-               smb_ReleaseUID(uidp);
+    smb_ioctl_t *iop;
+    long leftToCopy;
+    NCB *ncbp;
+    long code;
+    cm_user_t *userp;
+
+    iop = fidp->ioctlp;
+
+    userp = smb_GetUserFromVCP(vcp, inp);
+
+    /* Log the user */
+    {
+       smb_user_t *uidp;
+
+       uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+       if (uidp && uidp->unp) {
+           osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
+                    uidp->userID, userp,
+                    osi_LogSaveString(afsd_logp, uidp->unp->name));
+       } else if (uidp) {
+           osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
+                    uidp->userID, userp);
+       } else {
+           osi_Log1(afsd_logp, "Ioctl no uid user %x no name",
+                    userp);
        }
+       if (uidp) 
+           smb_ReleaseUID(uidp);
+    }  
 
-       iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
+    if (code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
 
-       code = smb_IoctlPrepareRead(fidp, iop, userp);
-       if (code) {
-               cm_ReleaseUser(userp);
-               smb_ReleaseFID(fidp);
-               return code;
-       }
+    code = smb_IoctlPrepareRead(fidp, iop, userp);
+    if (code) {
+       cm_ReleaseUser(userp);
+       return code;
+    }
 
-       leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied;
+    leftToCopy = (long)((iop->outDatap - iop->outAllocp) - iop->outCopied);
 
-       ncbp = outp->ncbp;
-       memset((char *)ncbp, 0, sizeof(NCB));
+    ncbp = outp->ncbp;
+    memset((char *)ncbp, 0, sizeof(NCB));
 
-       ncbp->ncb_length = (unsigned short) leftToCopy;
-       ncbp->ncb_lsn = (unsigned char) vcp->lsn;
-       ncbp->ncb_command = NCBSEND;
+    ncbp->ncb_length = (unsigned short) leftToCopy;
+    ncbp->ncb_lsn = (unsigned char) vcp->lsn;
+    ncbp->ncb_command = NCBSEND;
     /*ncbp->ncb_lana_num = smb_LANadapter;*/
-       ncbp->ncb_lana_num = vcp->lana;
+    ncbp->ncb_lana_num = vcp->lana;
 
-#ifndef DJGPP
-       ncbp->ncb_buffer = iop->outCopied + iop->outAllocp;
-       code = Netbios(ncbp);
-#else /* DJGPP */
-        dosmemput(iop->outCopied + iop->outAllocp, ncbp->ncb_length, rawBuf);
-        ncbp->ncb_buffer = rawBuf;
-        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-       code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
+    ncbp->ncb_buffer = iop->outCopied + iop->outAllocp;
+    code = Netbios(ncbp);
 
-       if (code != 0)
-               osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
+    if (code != 0)
+       osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
 
-       cm_ReleaseUser(userp);
-       smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
 
-       return 0;
+    return 0;
 }