unsigned char vdata[1];
} smb_t;
+/* flg2 values */
+
+#define SMB_FLAGS2_KNOWS_LONG_NAMES 0x0001
+#define SMB_FLAGS2_KNOWS_EAS 0x0002
+#define SMB_FLAGS2_SECURITY_SIGNATURE 0x0004
+#define SMB_FLAGS2_RESERVED1 0x0008
+#define SMB_FLAGS2_IS_LONG_NAME 0x0040
+#define SMB_FLAGS2_EXT_SEC 0x0800
+#define SMB_FLAGS2_DFS 0x1000
+#define SMB_FLAGS2_PAGING_IO 0x2000
+#define SMB_FLAGS2_ERR_STATUS 0x4000
+#define SMB_FLAGS2_UNICODE 0x8000
+
+/* Information Levels */
+#define SMB_INFO_STANDARD 1
+#define SMB_INFO_QUERY_EA_SIZE 2
+#define SMB_INFO_QUERY_EAS_FROM_LIST 3
+#define SMB_INFO_QUERY_ALL_EAS 4
+#define SMB_INFO_IS_NAME_VALID 6
+
+#define SMB_QUERY_FILE_BASIC_INFO 0x101
+#define SMB_QUERY_FILE_STANDARD_INFO 0x102
+#define SMB_QUERY_FILE_EA_INFO 0x103
+#define SMB_QUERY_FILE_NAME_INFO 0x104
+#define SMB_QUERY_FILE_ALL_INFO 0x107
+#define SMB_QUERY_FILE_ALT_NAME_INFO 0x108
+#define SMB_QUERY_FILE_STREAM_INFO 0x109
+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
+#define SMB_QUERY_FILE_UNIX_BASIC 0x200
+#define SMB_QUERY_FILE_UNIX_LINK 0x201
+
+#define SMB_SET_FILE_UNIX_BASIC 0x200
+#define SMB_SET_FILE_UNIX_LINK 0x201
+#define SMB_SET_FILE_UNIX_HLINK 0x203
+
/* more defines */
#define SMB_NOPCODES 256 /* # of opcodes in the dispatch table */
#define NEGOTIATE_SECURITY_SIGNATURES_REQUIRED 0x08
/* Capabilities */
-#define NTNEGOTIATE_CAPABILITY_RAWMODE 0x00000001L
-#define NTNEGOTIATE_CAPABILITY_MPXMODE 0x00000002L
-#define NTNEGOTIATE_CAPABILITY_UNICODE 0x00000004L
-#define NTNEGOTIATE_CAPABILITY_LARGEFILES 0x00000008L
-#define NTNEGOTIATE_CAPABILITY_NTSMB 0x00000010L
-#define NTNEGOTIATE_CAPABILITY_RPCAPI 0x00000020L
-#define NTNEGOTIATE_CAPABILITY_NTSTATUS 0x00000040L
-#define NTNEGOTIATE_CAPABILITY_LEVEL_II_OPLOCKS 0x00000080L
+#define NTNEGOTIATE_CAPABILITY_RAWMODE 0x00000001L
+#define NTNEGOTIATE_CAPABILITY_MPXMODE 0x00000002L
+#define NTNEGOTIATE_CAPABILITY_UNICODE 0x00000004L
+#define NTNEGOTIATE_CAPABILITY_LARGEFILES 0x00000008L
+#define NTNEGOTIATE_CAPABILITY_NTSMB 0x00000010L
+#define NTNEGOTIATE_CAPABILITY_RPCAPI 0x00000020L
+#define NTNEGOTIATE_CAPABILITY_NTSTATUS 0x00000040L
+#define NTNEGOTIATE_CAPABILITY_LEVEL_II_OPLOCKS 0x00000080L
#define NTNEGOTIATE_CAPABILITY_LOCK_AND_READ 0x00000100L
-#define NTNEGOTIATE_CAPABILITY_NTFIND 0x00000200L
-#define NTNEGOTIATE_CAPABILITY_DFS 0x00001000L
+#define NTNEGOTIATE_CAPABILITY_NTFIND 0x00000200L
+#define NTNEGOTIATE_CAPABILITY_DFS 0x00001000L
#define NTNEGOTIATE_CAPABILITY_NT_INFO_PASSTHRU 0x00002000L
#define NTNEGOTIATE_CAPABILITY_BULK_TRANSFER 0x20000000L
-#define NTNEGOTIATE_CAPABILITY_COMPRESSED 0x40000000L
+#define NTNEGOTIATE_CAPABILITY_COMPRESSED 0x40000000L
#define NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY 0x80000000L
/* a packet structure for receiving SMB messages; locked by smb_globalLock.
#define SMB_FID_NTOPEN 0x100 /* have dscp and pathp */
/*
- * SMB file attributes
+ * SMB file attributes (32-bit)
*/
-#define SMB_ATTR_ARCHIVE 0x20
-#define SMB_ATTR_COMPRESSED 0x800 /* file or dir is compressed */
-#define SMB_ATTR_NORMAL 0x80 /* normal file. Only valid if used alone */
-#define SMB_ATTR_HIDDEN 0x2 /* hidden file for the purpose of dir listings */
-#define SMB_ATTR_READONLY 0x1
-#define SMB_ATTR_TEMPORARY 0x100
-#define SMB_ATTR_DIRECTORY 0x10
-#define SMB_ATTR_SYSTEM 0x4
+#define SMB_ATTR_READONLY 0x0001
+#define SMB_ATTR_HIDDEN 0x0002 /* hidden file for the purpose of dir listings */
+#define SMB_ATTR_SYSTEM 0x0004
+#define SMB_ATTR_VOLUMEID 0x0008 /* obsolete */
+#define SMB_ATTR_DIRECTORY 0x0010
+#define SMB_ATTR_ARCHIVE 0x0020
+#define SMB_ATTR_DEVICE 0x0040
+#define SMB_ATTR_NORMAL 0x0080 /* normal file. Only valid if used alone */
+#define SMB_ATTR_TEMPORARY 0x0100
+#define SMB_ATTR_SPARSE_FILE 0x0200
+#define SMB_ATTR_REPARSE_POINT 0x0400
+#define SMB_ATTR_COMPRESSED 0x0800 /* file or dir is compressed */
+#define SMB_ATTR_OFFLINE 0x1000
+#define SMB_ATTR_NOT_CONTENT_INDEXED 0x2000
+#define SMB_ATTR_ENCRYPTED 0x4000
/* for tracking in-progress directory searches */
typedef struct smb_dirSearch {
}
#define SMB_SUPPORT_SEARCH_BITS 0x0001
+#define SMB_SHARE_IS_IN_DFS 0x0002
long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
- if(!ipc) {
+ if (!ipc) {
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
if (uidp)
if (vcp->flags & SMB_VCFLAG_USENT)
{
int policy = smb_FindShareCSCPolicy(shareName);
- smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2));
+ smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS |
+#ifdef DFS_SUPPORT
+ SMB_SHARE_IS_IN_DFS |
+#endif
+ (policy << 2));
}
} else {
smb_SetSMBParm(outp, 2, 0);
lock_ObtainMutex(&tidp->mx);
tidp->userp = userp;
tidp->pathname = sharePath;
- if(ipc) tidp->flags |= SMB_TIDFLAG_IPC;
+ if (ipc)
+ tidp->flags |= SMB_TIDFLAG_IPC;
lock_ReleaseMutex(&tidp->mx);
smb_ReleaseTID(tidp);
((smb_t *)inp)->tid = newTid;
tp = smb_GetSMBData(outp, NULL);
if (!ipc) {
+ /* XXX - why is this a drive letter? - jaltman */
*tp++ = 'A';
*tp++ = ':';
*tp++ = 0;
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
- smbp->flg2 |= 0x40; /* IS_LONG_NAME */
+ smbp->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
/* now copy important fields from the tran 2 packet */
smbp->com = t2p->com;
smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
- smbp->flg2 |= 0x4000;
+ smbp->flg2 |= SMB_FLAGS2_ERR_STATUS;
}
else {
smbp->rcls = errClass;
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
- smbp->flg2 |= 0x40; /* IS_LONG_NAME */
+ smbp->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
/* now copy important fields from the tran 2 packet */
smbp->com = t2p->com;
if (infoLevel == 0)
totalData = sizeof(smb_rap_share_info_0_t);
- else if(infoLevel == 1)
+ else if(infoLevel == SMB_INFO_STANDARD)
totalData = sizeof(smb_rap_share_info_1_t) + 1; /* + empty string */
- else if(infoLevel == 2)
+ else if(infoLevel == SMB_INFO_QUERY_EA_SIZE)
totalData = sizeof(smb_rap_share_info_2_t) + 2; /* + two empty strings */
else
return CM_ERROR_INVAL;
smb_rap_share_info_0_t * info = (smb_rap_share_info_0_t *) outp->datap;
strncpy(info->shi0_netname, shareName, sizeof(info->shi0_netname)-1);
info->shi0_netname[sizeof(info->shi0_netname)-1] = 0;
- } else if(infoLevel == 1) {
+ } else if(infoLevel == SMB_INFO_STANDARD) {
smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
strncpy(info->shi1_netname, shareName, sizeof(info->shi1_netname)-1);
info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
info0 = (smb_rap_server_info_0_t *) outp->datap;
cstrp = (char *) (info0 + 1);
strcpy(info0->sv0_name, "AFS");
- } else { /* infoLevel == 1 */
+ } else { /* infoLevel == SMB_INFO_STANDARD */
info1 = (smb_rap_server_info_1_t *) outp->datap;
cstrp = (char *) (info1 + 1);
strcpy(info1->sv1_name, "AFS");
case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break;
case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break;
case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break;
+ case 0x200: /* CIFS Unix Info */
+ case 0x301: /* Mac FS Info */
default: return CM_ERROR_INVAL;
}
cm_InitReq(&req);
infoLevel = p->parmsp[0];
- if (infoLevel == 6) nbytesRequired = 0;
- else if (infoLevel == 1) nbytesRequired = 22;
- else if (infoLevel == 2) nbytesRequired = 26;
- else if (infoLevel == 0x101) nbytesRequired = 40;
- else if (infoLevel == 0x102) nbytesRequired = 24;
- else if (infoLevel == 0x103) nbytesRequired = 4;
- else if (infoLevel == 0x108) nbytesRequired = 30;
+ if (infoLevel == SMB_INFO_IS_NAME_VALID)
+ nbytesRequired = 0;
+ else if (infoLevel == SMB_INFO_STANDARD)
+ nbytesRequired = 22;
+ else if (infoLevel == SMB_INFO_QUERY_EA_SIZE)
+ nbytesRequired = 26;
+ else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+ nbytesRequired = 40;
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+ nbytesRequired = 24;
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ nbytesRequired = 4;
+ else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO)
+ nbytesRequired = 30;
else {
osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
* the syntax, so we just OK things now. In particular, we're *not*
* being asked to verify anything about the state of any parent dirs.
*/
- if (infoLevel == 6) {
+ if (infoLevel == SMB_INFO_IS_NAME_VALID) {
smb_SendTran2Packet(vcp, outp, opx);
smb_FreeTran2Packet(outp);
return 0;
* yet been evaluated and for directories that haven't yet been
* fetched.
*/
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastComp,
(char *)(&p->parmsp[3]));
goto done;
}
- if (infoLevel == 1 || infoLevel == 2) {
+ if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
*((u_long *)op) = dosTime; op += 4; /* creation time */
*((u_long *)op) = dosTime; op += 4; /* access time */
attributes = smb_Attributes(scp);
*((u_short *)op) = attributes; op += 2; /* attributes */
}
- else if (infoLevel == 0x101) {
+ else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)op) = ft; op += 8; /* creation time */
*((FILETIME *)op) = ft; op += 8; /* last access time */
*((u_long *)op) = extAttributes; op += 4; /* extended attribs */
*((u_long *)op) = 0; op += 4; /* don't know what this is */
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
*((u_long *)op) = scp->linkCount; op += 4;
*op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
*op++ = 0;
}
- else if (infoLevel == 0x103) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
memset(op, 0, 4); op += 4; /* EA size */
}
/* now, if we are being asked about extended attrs, return a 0 size */
- if (infoLevel == 2) {
+ if (infoLevel == SMB_INFO_QUERY_EA_SIZE) {
*((u_long *)op) = 0; op += 4;
}
}
infoLevel = p->parmsp[1];
- if (infoLevel == 0x101) nbytesRequired = 40;
- else if (infoLevel == 0x102) nbytesRequired = 24;
- else if (infoLevel == 0x103) nbytesRequired = 4;
- else if (infoLevel == 0x104) nbytesRequired = 6;
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+ nbytesRequired = 40;
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+ nbytesRequired = 24;
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ nbytesRequired = 4;
+ else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+ nbytesRequired = 6;
else {
osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
* Marshall the output data.
*/
op = outp->datap;
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)op) = ft; op += 8; /* creation time */
*((FILETIME *)op) = ft; op += 8; /* last access time */
*((u_long *)op) = attributes; op += 4;
*((u_long *)op) = 0; op += 4;
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
*((u_long *)op) = scp->linkCount; op += 4;
*op++ = 0;
*op++ = 0;
}
- else if (infoLevel == 0x103) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
*((u_long *)op) = 0; op += 4;
}
- else if (infoLevel == 0x104) {
+ else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
unsigned long len;
char *name;
return 0;
}
- if (infoLevel == 0x102 && !(fidp->flags & SMB_FID_OPENDELETE)) {
+ if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
smb_ReleaseFID(fidp);
return 0;
}
- if ((infoLevel == 0x103 || infoLevel == 0x104)
+ if ((infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO)
&& !(fidp->flags & SMB_FID_OPENWRITE)) {
smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
smb_ReleaseFID(fidp);
scp = fidp->scp;
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
FILETIME lastMod;
unsigned int attribute;
cm_attr_t attr;
else
code = 0;
}
- else if (infoLevel == 0x103 || infoLevel == 0x104) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO) {
LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
cm_attr_t attr;
attr.length.HighPart = size.HighPart;
code = cm_SetAttr(scp, &attr, userp, &req);
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
if (*((char *)(p->datap))) {
code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
&req);
long
smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
+ /* This is a UNICODE only request (bit15 of Flags2) */
+ /* The TID must be IPC$ */
+
+ /* The documentation for the Flags response field is contradictory */
+
+ /* Use Version 1 Referral Element Format */
+ /* ServerType = 0; indicates the next server should be queried for the file */
+ /* ReferralFlags = 0x01; PathConsumed characters should be stripped */
+ /* Node = UnicodeString of UNC path of the next share name */
+
osi_Log0(smb_logp,"ReceiveTran2GetDFSReferral - NOT_SUPPORTED");
return CM_ERROR_BADOP;
}
long
smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
+ /* This is a UNICODE only request (bit15 of Flags2) */
+
+ /* There is nothing we can do about this operation. The client is going to
+ * tell us that there is a Version 1 Referral Element for which there is a DFS Error.
+ * Unfortunately, there is really nothing we can do about it other then log it
+ * somewhere. Even then I don't think there is anything for us to do.
+ * So let's return an error value.
+ */
+
osi_Log0(smb_logp,"ReceiveTran2ReportDFSInconsistency - NOT_SUPPORTED");
return CM_ERROR_BADOP;
}
/* Need 8.3 name? */
NeedShortName = 0;
- if (infoLevel == 0x104
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO
&& dep->fid.vnode != 0
&& !cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
/* standard dir entry stuff */
if (infoLevel < 0x101)
ohbytes = 23; /* pre-NT */
- else if (infoLevel == 0x103)
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
ohbytes = 12; /* NT names only */
else
ohbytes = 64; /* NT */
- if (infoLevel == 0x104)
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
ohbytes += 26; /* Short name & length */
if (searchFlags & 4) {
if (infoLevel <= 0x101)
*(origOp + ohbytes - 1) = (unsigned char) onbytes;
- else if (infoLevel == 0x103)
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
*((u_long *)(op + 8)) = onbytes;
else
*((u_long *)(op + 60)) = onbytes;
CharToOem(origOp+ohbytes, origOp+ohbytes);
/* Short name if requested and needed */
- if (infoLevel == 0x104) {
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
if (NeedShortName) {
strcpy(op + 70, shortName);
if (smb_StoreAnsiFilenames)
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
- ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */
+ ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
switch (function) {
case 6:
((smb_t *) watch)->errLow = 0;
((smb_t *) watch)->errHigh = 0;
/* Set NT Status codes flag */
- ((smb_t *) watch)->flg2 |= 0x4000;
+ ((smb_t *) watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
}
smb_SendPacket(vcp, watch);
((smb_t *)watch)->reh = 0x1;
((smb_t *)watch)->errLow = 0;
((smb_t *)watch)->errHigh = 0xC0;
- ((smb_t *)watch)->flg2 |= 0x4000;
+ ((smb_t *)watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
smb_SendPacket(vcp, watch);
if (watch->vcp)
smb_ReleaseVC(watch->vcp);