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>
15 #pragma warning(disable: 4005)
28 #include <rx/rx_prototypes.h>
29 #include <WINNT\afsreg.h>
33 #include "lanahelper.h"
35 #define STRSAFE_NO_DEPRECATE
38 /* These characters are illegal in Windows filenames */
39 static clientchar_t *illegalChars = _C("\\/:*?\"<>|");
41 static int smbShutdownFlag = 0;
42 static int smb_ListenerState = SMB_LISTENER_UNINITIALIZED;
44 int smb_LogoffTokenTransfer;
45 time_t smb_LogoffTransferTimeout;
47 int smb_StoreAnsiFilenames = 0;
49 DWORD last_msg_time = 0;
53 unsigned int sessionGen = 0;
55 extern void afsi_log(char *pattern, ...);
56 extern HANDLE afsi_file;
57 extern int powerStateSuspended;
59 osi_hyper_t hzero = {0, 0};
60 osi_hyper_t hones = {0xFFFFFFFF, -1};
63 osi_rwlock_t smb_globalLock;
64 osi_rwlock_t smb_rctLock;
65 osi_mutex_t smb_ListenerLock;
66 osi_mutex_t smb_StartedLock;
68 unsigned char smb_LANadapter = LANA_INVALID;
69 unsigned char smb_sharename[NCBNAMSZ+1] = {0};
70 int smb_LanAdapterChangeDetected = 0;
71 afs_uint32 smb_AsyncStore = 1;
72 afs_uint32 smb_AsyncStoreSize = CM_CONFIGDEFAULT_ASYNCSTORESIZE;
74 BOOL isGateway = FALSE;
77 long smb_maxObsConcurrentCalls=0;
78 long smb_concurrentCalls=0;
80 smb_dispatch_t smb_dispatchTable[SMB_NOPCODES];
82 smb_packet_t *smb_packetFreeListp;
83 smb_ncb_t *smb_ncbFreeListp;
85 afs_uint32 smb_NumServerThreads;
87 afs_uint32 numNCBs, numSessions, numVCs;
89 int smb_maxVCPerServer;
90 int smb_maxMpxRequests;
92 int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
94 ULONG smb_lsaSecPackage;
95 LSA_STRING smb_lsaLogonOrigin;
97 #define NCB_MAX MAXIMUM_WAIT_OBJECTS
98 EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX];
99 EVENT_HANDLE **NCBreturns;
100 EVENT_HANDLE **NCBShutdown;
101 EVENT_HANDLE *smb_ServerShutdown;
102 EVENT_HANDLE ListenerShutdown[256];
103 DWORD NCBsessions[NCB_MAX];
105 struct smb_packet *bufs[NCB_MAX];
107 #define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4
108 EVENT_HANDLE SessionEvents[SESSION_MAX];
109 unsigned short LSNs[SESSION_MAX];
110 int lanas[SESSION_MAX];
111 BOOL dead_sessions[SESSION_MAX];
114 osi_mutex_t smb_RawBufLock;
117 #define SMB_MASKFLAG_TILDE 1
118 #define SMB_MASKFLAG_CASEFOLD 2
120 #define RAWTIMEOUT INFINITE
123 typedef struct raw_write_cont {
132 /* dir search stuff */
133 long smb_dirSearchCounter = 1;
134 smb_dirSearch_t *smb_firstDirSearchp;
135 smb_dirSearch_t *smb_lastDirSearchp;
137 /* Initial mode bits for files and directories. Set to 0 to use
139 int smb_unixModeDefaultFile = 0666;
140 int smb_unixModeDefaultDir = 0777;
142 /* hide dot files? */
143 int smb_hideDotFiles;
145 /* Negotiate Unicode support? */
148 /* global state about V3 protocols */
149 int smb_useV3; /* try to negotiate V3 */
151 static int showErrors = 0;
152 /* MessageBox or something like it */
153 int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT)
157 * Time in Unix format of midnight, 1/1/1970 local time.
158 * When added to dosUTime, gives Unix (AFS) time.
160 time_t smb_localZero = 0;
162 char *smb_localNamep = NULL;
164 smb_vc_t *smb_allVCsp;
165 smb_vc_t *smb_deadVCsp;
167 smb_username_t *usernamesp = NULL;
169 smb_waitingLockRequest_t *smb_allWaitingLocks;
172 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
173 NCB *ncbp, raw_write_cont_t *rwcp);
174 int smb_NetbiosInit(int);
177 void smb_LogPacket(smb_packet_t *packet);
178 #endif /* LOG_PACKET */
180 clientchar_t smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = _C(""); /* domain name */
181 int smb_ServerDomainNameLength = 0;
182 clientchar_t smb_ServerOS[] = _C("Windows 5.0"); /* Faux OS String */
183 int smb_ServerOSLength = lengthof(smb_ServerOS);
184 clientchar_t smb_ServerLanManager[] = _C("Windows 2000 LAN Manager"); /* Faux LAN Manager string */
185 int smb_ServerLanManagerLength = lengthof(smb_ServerLanManager);
187 /* Faux server GUID. This is never checked. */
188 GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
190 void smb_InitReq(cm_req_t *reqp)
193 reqp->flags |= CM_REQ_SOURCE_SMB;
196 const char * ncb_error_string(int code)
200 case 0x01: s = "NRC_BUFLEN llegal buffer length"; break;
201 case 0x03: s = "NRC_ILLCMD illegal command"; break;
202 case 0x05: s = "NRC_CMDTMO command timed out"; break;
203 case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break;
204 case 0x07: s = "NRC_BADDR illegal buffer address"; break;
205 case 0x08: s = "NRC_SNUMOUT session number out of range"; break;
206 case 0x09: s = "NRC_NORES no resource available"; break;
207 case 0x0a: s = "NRC_SCLOSED asession closed"; break;
208 case 0x0b: s = "NRC_CMDCAN command cancelled"; break;
209 case 0x0d: s = "NRC_DUPNAME duplicate name"; break;
210 case 0x0e: s = "NRC_NAMTFUL name table full"; break;
211 case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break;
212 case 0x11: s = "NRC_LOCTFUL local session table full"; break;
213 case 0x12: s = "NRC_REMTFUL remote session table full"; break;
214 case 0x13: s = "NRC_ILLNN illegal name number"; break;
215 case 0x14: s = "NRC_NOCALL no callname"; break;
216 case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME"; break;
217 case 0x16: s = "NRC_INUSE name in use on remote adapter"; break;
218 case 0x17: s = "NRC_NAMERR name deleted"; break;
219 case 0x18: s = "NRC_SABORT session ended abnormally"; break;
220 case 0x19: s = "NRC_NAMCONF name conflict detected"; break;
221 case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying"; break;
222 case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
223 case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid"; break;
224 case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break;
225 case 0x26: s = "NRC_CANCEL command not valid to cancel"; break;
226 case 0x30: s = "NRC_DUPENV name defined by anther local process"; break;
227 case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required"; break;
228 case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted"; break;
229 case 0x36: s = "NRC_MAXAPPS max number of applications exceeded"; break;
230 case 0x37: s = "NRC_NOSAPS no saps available for netbios"; break;
231 case 0x38: s = "NRC_NORESOURCES requested resources are not available"; break;
232 case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment"; break;
233 case 0x3B: s = "NRC_INVDDID invalid NCB DDID"; break;
234 case 0x3C: s = "NRC_LOCKFAILlock of user area failed"; break;
235 case 0x3f: s = "NRC_OPENERR NETBIOS not loaded"; break;
236 case 0x40: s = "NRC_SYSTEM system error"; break;
237 default: s = "unknown error";
243 char * myCrt_Dispatch(int i)
248 return "(00)ReceiveCoreMakeDir";
250 return "(01)ReceiveCoreRemoveDir";
252 return "(02)ReceiveCoreOpen";
254 return "(03)ReceiveCoreCreate";
256 return "(04)ReceiveCoreClose";
258 return "(05)ReceiveCoreFlush";
260 return "(06)ReceiveCoreUnlink";
262 return "(07)ReceiveCoreRename";
264 return "(08)ReceiveCoreGetFileAttributes";
266 return "(09)ReceiveCoreSetFileAttributes";
268 return "(0a)ReceiveCoreRead";
270 return "(0b)ReceiveCoreWrite";
272 return "(0c)ReceiveCoreLockRecord";
274 return "(0d)ReceiveCoreUnlockRecord";
276 return "(0e)SendCoreBadOp";
278 return "(0f)ReceiveCoreCreate";
280 return "(10)ReceiveCoreCheckPath";
282 return "(11)SendCoreBadOp";
284 return "(12)ReceiveCoreSeek";
286 return "(1a)ReceiveCoreReadRaw";
288 return "(1d)ReceiveCoreWriteRawDummy";
290 return "(22)ReceiveV3SetAttributes";
292 return "(23)ReceiveV3GetAttributes";
294 return "(24)ReceiveV3LockingX";
296 return "(25)ReceiveV3Trans";
298 return "(26)ReceiveV3Trans[aux]";
300 return "(29)SendCoreBadOp";
302 return "(2b)ReceiveCoreEcho";
304 return "(2d)ReceiveV3OpenX";
306 return "(2e)ReceiveV3ReadX";
308 return "(2f)ReceiveV3WriteX";
310 return "(32)ReceiveV3Tran2A";
312 return "(33)ReceiveV3Tran2A[aux]";
314 return "(34)ReceiveV3FindClose";
316 return "(35)ReceiveV3FindNotifyClose";
318 return "(70)ReceiveCoreTreeConnect";
320 return "(71)ReceiveCoreTreeDisconnect";
322 return "(72)ReceiveNegotiate";
324 return "(73)ReceiveV3SessionSetupX";
326 return "(74)ReceiveV3UserLogoffX";
328 return "(75)ReceiveV3TreeConnectX";
330 return "(80)ReceiveCoreGetDiskAttributes";
332 return "(81)ReceiveCoreSearchDir";
336 return "(83)FindUnique";
338 return "(84)FindClose";
340 return "(A0)ReceiveNTTransact";
342 return "(A2)ReceiveNTCreateX";
344 return "(A4)ReceiveNTCancel";
346 return "(A5)ReceiveNTRename";
348 return "(C0)OpenPrintFile";
350 return "(C1)WritePrintFile";
352 return "(C2)ClosePrintFile";
354 return "(C3)GetPrintQueue";
356 return "(D8)ReadBulk";
358 return "(D9)WriteBulk";
360 return "(DA)WriteBulkData";
362 return "unknown SMB op";
366 char * myCrt_2Dispatch(int i)
371 return "unknown SMB op-2";
373 return "S(00)CreateFile_ReceiveTran2Open";
375 return "S(01)FindFirst_ReceiveTran2SearchDir";
377 return "S(02)FindNext_ReceiveTran2SearchDir"; /* FindNext */
379 return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
381 return "S(04)SetFileSystem_ReceiveTran2SetFSInfo";
383 return "S(05)QueryPathInfo_ReceiveTran2QPathInfo";
385 return "S(06)SetPathInfo_ReceiveTran2SetPathInfo";
387 return "S(07)QueryFileInfo_ReceiveTran2QFileInfo";
389 return "S(08)SetFileInfo_ReceiveTran2SetFileInfo";
391 return "S(09)_ReceiveTran2FSCTL";
393 return "S(0a)_ReceiveTran2IOCTL";
395 return "S(0b)_ReceiveTran2FindNotifyFirst";
397 return "S(0c)_ReceiveTran2FindNotifyNext";
399 return "S(0d)_ReceiveTran2CreateDirectory";
401 return "S(0e)_ReceiveTran2SessionSetup";
403 return "S(0f)_QueryFileSystemInformationFid";
405 return "S(10)_ReceiveTran2GetDfsReferral";
407 return "S(11)_ReceiveTran2ReportDfsInconsistency";
411 char * myCrt_RapDispatch(int i)
416 return "unknown RAP OP";
418 return "RAP(0)NetShareEnum";
420 return "RAP(1)NetShareGetInfo";
422 return "RAP(13)NetServerGetInfo";
424 return "RAP(63)NetWkStaGetInfo";
428 char * myCrt_NmpipeDispatch(int i)
431 case SMB_TRANS_SET_NMPIPE_STATE:
432 return "SET NMPIPE STATE";
434 case SMB_TRANS_RAW_READ_NMPIPE:
435 return "RAW READ NMPIPE";
437 case SMB_TRANS_QUERY_NMPIPE_STATE:
438 return "QUERY NMPIPE STATE";
440 case SMB_TRANS_QUERY_NMPIPE_INFO:
441 return "QUERY NMPIPE INFO";
443 case SMB_TRANS_PEEK_NMPIPE:
444 return "PEEK NMPIPE";
446 case SMB_TRANS_TRANSACT_NMPIPE:
447 return "TRANSACT NMPIPE";
449 case SMB_TRANS_RAW_WRITE_NMPIPE:
450 return "WRITE NMPIPE";
452 case SMB_TRANS_READ_NMPIPE:
453 return "READ NMPIPE";
455 case SMB_TRANS_WRITE_NMPIPE:
456 return "WRITE NMPIPE";
458 case SMB_TRANS_WAIT_NMPIPE:
459 return "WAIT NMPIPE";
461 case SMB_TRANS_CALL_NMPIPE:
462 return "CALL NMPIPE";
467 /* scache must be locked */
468 unsigned int smb_Attributes(cm_scache_t *scp)
472 if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
473 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
474 scp->fileType == CM_SCACHETYPE_INVALID)
476 attrs = SMB_ATTR_DIRECTORY;
477 #ifdef SPECIAL_FOLDERS
478 attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
479 #endif /* SPECIAL_FOLDERS */
480 } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
481 attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
486 * We used to mark a file RO if it was in an RO volume, but that
487 * turns out to be impolitic in NT. See defect 10007.
490 if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
491 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
493 if ((scp->unixModeBits & 0200) == 0)
494 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
500 void smb_SetInitialModeBitsForFile(int smb_attr, cm_attr_t * attr)
502 if (smb_unixModeDefaultFile != 0) {
503 attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
504 attr->unixModeBits = smb_unixModeDefaultFile;
505 if (smb_attr & SMB_ATTR_READONLY)
506 attr->unixModeBits &= ~0222;
510 void smb_SetInitialModeBitsForDir(int smb_attr, cm_attr_t * attr)
512 if (smb_unixModeDefaultDir != 0) {
513 attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
514 attr->unixModeBits = smb_unixModeDefaultDir;
518 /* Check if the named file/dir is a dotfile/dotdir */
519 /* String pointed to by lastComp can have leading slashes, but otherwise should have
520 no other patch components */
521 unsigned int smb_IsDotFile(clientchar_t *lastComp) {
525 /* skip over slashes */
526 for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
531 /* nulls, curdir and parent dir doesn't count */
537 if(*(s+1) == _C('.') && !*(s + 2))
544 static int ExtractBits(WORD bits, short start, short len)
551 num = bits << (16 - end);
552 num = num >> ((16 - end) + start);
557 void ShowUnixTime(char *FuncName, time_t unixTime)
562 cm_LargeSearchTimeFromUnixTime(&ft, unixTime);
564 if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
565 osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
567 int day, month, year, sec, min, hour;
570 day = ExtractBits(wDate, 0, 5);
571 month = ExtractBits(wDate, 5, 4);
572 year = ExtractBits(wDate, 9, 7) + 1980;
574 sec = ExtractBits(wTime, 0, 5);
575 min = ExtractBits(wTime, 5, 6);
576 hour = ExtractBits(wTime, 11, 5);
578 sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
579 osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
583 /* Determine if we are observing daylight savings time */
584 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
586 TIME_ZONE_INFORMATION timeZoneInformation;
587 SYSTEMTIME utc, local, localDST;
589 /* Get the time zone info. NT uses this to calc if we are in DST. */
590 GetTimeZoneInformation(&timeZoneInformation);
592 /* Return the daylight bias */
593 *pDstBias = timeZoneInformation.DaylightBias;
595 /* Return the bias */
596 *pBias = timeZoneInformation.Bias;
598 /* Now determine if DST is being observed */
600 /* Get the UTC (GMT) time */
603 /* Convert UTC time to local time using the time zone info. If we are
604 observing DST, the calculated local time will include this.
606 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &localDST);
608 /* Set the daylight bias to 0. The daylight bias is the amount of change
609 * in time that we use for daylight savings time. By setting this to 0
610 * we cause there to be no change in time during daylight savings time.
612 timeZoneInformation.DaylightBias = 0;
614 /* Convert the utc time to local time again, but this time without any
615 adjustment for daylight savings time.
617 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &local);
619 /* If the two times are different, then it means that the localDST that
620 we calculated includes the daylight bias, and therefore we are
621 observing daylight savings time.
623 *pDST = localDST.wHour != local.wHour;
627 void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
629 BOOL dst; /* Will be TRUE if observing DST */
630 LONG dstBias; /* Offset from local time if observing DST */
631 LONG bias; /* Offset from GMT for local time */
634 * This function will adjust the last write time to compensate
635 * for two bugs in the smb client:
637 * 1) During Daylight Savings Time, the LastWriteTime is ahead
638 * in time by the DaylightBias (ignoring the sign - the
639 * DaylightBias is always stored as a negative number). If
640 * the DaylightBias is -60, then the LastWriteTime will be
641 * ahead by 60 minutes.
643 * 2) If the local time zone is a positive offset from GMT, then
644 * the LastWriteTime will be the correct local time plus the
645 * Bias (ignoring the sign - a positive offset from GMT is
646 * always stored as a negative Bias). If the Bias is -120,
647 * then the LastWriteTime will be ahead by 120 minutes.
649 * These bugs can occur at the same time.
652 GetTimeZoneInfo(&dst, &dstBias, &bias);
654 /* First adjust for DST */
656 *pLastWriteTime -= (-dstBias * 60); /* Convert dstBias to seconds */
658 /* Now adjust for a positive offset from GMT (a negative bias). */
660 *pLastWriteTime -= (-bias * 60); /* Convert bias to seconds */
663 void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
665 time_t diff_t = unixTime - smb_localZero;
666 #if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
667 osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
669 *dosUTimep = (afs_uint32)diff_t;
672 void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
674 *unixTimep = dosTime + smb_localZero;
677 void smb_MarkAllVCsDead(smb_vc_t * exclude)
680 smb_vc_t **vcp_to_cleanup = NULL;
681 int n_to_cleanup = 0;
684 osi_Log1(smb_logp, "Marking all VCs as dead excluding %p", exclude);
686 lock_ObtainWrite(&smb_globalLock); /* for dead_sessions[] */
687 lock_ObtainWrite(&smb_rctLock);
688 for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
690 if (vcp->magic != SMB_VC_MAGIC)
691 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
697 lock_ObtainMutex(&vcp->mx);
698 if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
699 vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
700 lock_ReleaseMutex(&vcp->mx);
701 dead_sessions[vcp->session] = TRUE;
703 lock_ReleaseMutex(&vcp->mx);
708 vcp_to_cleanup = malloc(sizeof(vcp_to_cleanup[0]) * n_to_cleanup);
710 for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
714 vcp_to_cleanup[i++] = vcp;
715 smb_HoldVCNoLock(vcp);
718 osi_assert(i == n_to_cleanup);
720 lock_ReleaseWrite(&smb_rctLock);
721 lock_ReleaseWrite(&smb_globalLock);
723 for (i=0; i < n_to_cleanup; i++) {
724 smb_CleanupDeadVC(vcp_to_cleanup[i]);
725 smb_ReleaseVC(vcp_to_cleanup[i]);
726 vcp_to_cleanup[i] = 0;
729 free(vcp_to_cleanup);
732 #ifdef DEBUG_SMB_REFCOUNT
733 smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line)
735 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
740 lock_ObtainWrite(&smb_globalLock); /* for numVCs */
741 lock_ObtainWrite(&smb_rctLock);
742 for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
743 if (vcp->magic != SMB_VC_MAGIC)
744 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
747 lock_ObtainMutex(&vcp->mx);
748 if (lsn == vcp->lsn && lana == vcp->lana &&
749 !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
750 lock_ReleaseMutex(&vcp->mx);
751 smb_HoldVCNoLock(vcp);
754 lock_ReleaseMutex(&vcp->mx);
756 if (!vcp && (flags & SMB_FLAG_CREATE)) {
757 vcp = malloc(sizeof(*vcp));
758 memset(vcp, 0, sizeof(*vcp));
759 vcp->vcID = ++numVCs;
760 vcp->magic = SMB_VC_MAGIC;
761 vcp->refCount = 2; /* smb_allVCsp and caller */
764 vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
765 vcp->nextp = smb_allVCsp;
767 lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
772 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
773 /* We must obtain a challenge for extended auth
774 * in case the client negotiates smb v3
776 NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
777 MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
778 PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp = NULL;
779 ULONG lsaRespSize = 0;
781 lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
783 nts = LsaCallAuthenticationPackage( smb_lsaHandle,
790 if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS) {
791 osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
792 nts, ntsEx, sizeof(lsaReq), lsaRespSize);
793 afsi_log("MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize %u",
794 nts, ntsEx, lsaRespSize);
796 osi_assertx(nts == STATUS_SUCCESS, "LsaCallAuthenticationPackage failed"); /* this had better work! */
798 if (ntsEx == STATUS_SUCCESS) {
799 memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
802 * This will cause the subsequent authentication to fail but
803 * that is better than us dereferencing a NULL pointer and
806 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
809 LsaFreeReturnBuffer(lsaResp);
812 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
814 if (numVCs >= CM_SESSION_RESERVED) {
816 osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
819 #ifdef DEBUG_SMB_REFCOUNT
821 afsi_log("%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
822 osi_Log4(smb_logp,"%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
825 lock_ReleaseWrite(&smb_rctLock);
826 lock_ReleaseWrite(&smb_globalLock);
830 static int smb_Is8Dot3StarMask(clientchar_t *maskp)
835 for(i=0; i<11; i++) {
837 if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
843 static int smb_IsStarMask(clientchar_t *maskp)
849 if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
855 #ifdef DEBUG_SMB_REFCOUNT
856 void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
857 #define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
859 void smb_ReleaseVCInternal(smb_vc_t *vcp)
865 lock_AssertWrite(&smb_rctLock);
868 if (vcp->refCount == 0) {
869 if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
870 #ifdef DEBUG_SMB_REFCOUNT
871 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
872 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
874 /* remove VCP from smb_deadVCsp */
875 for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
881 lock_FinalizeMutex(&vcp->mx);
882 memset(vcp,0,sizeof(smb_vc_t));
885 #ifdef DEBUG_SMB_REFCOUNT
886 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is alive ref %d", file, line, vcp, vcp->refCount);
888 for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
892 osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
893 avcp?"":"not ",vcp, vcp->refCount);
895 /* This is a wrong. However, I suspect that there is an undercount
896 * and I don't want to release 1.4.1 in a state that will allow
897 * smb_vc_t objects to be deallocated while still in the
898 * smb_allVCsp list. The list is supposed to keep a reference
899 * to the smb_vc_t. Put it back.
903 #ifdef DEBUG_SMB_REFCOUNT
904 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
905 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
909 } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
910 /* The reference count is non-zero but the VC is dead.
911 * This implies that some FIDs, TIDs, etc on the VC have yet to
912 * be cleaned up. If we were not called by smb_CleanupDeadVC(),
913 * add a reference that will be dropped by
914 * smb_CleanupDeadVC() and try to cleanup the VC again.
915 * Eventually the refCount will drop to zero when all of the
916 * active threads working with the VC end their task.
918 if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) {
919 vcp->refCount++; /* put the refCount back */
920 lock_ReleaseWrite(&smb_rctLock);
921 smb_CleanupDeadVC(vcp);
922 #ifdef DEBUG_SMB_REFCOUNT
923 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
924 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
926 lock_ObtainWrite(&smb_rctLock);
929 #ifdef DEBUG_SMB_REFCOUNT
930 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
931 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
936 #ifdef DEBUG_SMB_REFCOUNT
937 void smb_ReleaseVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
939 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
942 lock_AssertWrite(&smb_rctLock);
943 osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
944 smb_ReleaseVCInternal(vcp);
947 #ifdef DEBUG_SMB_REFCOUNT
948 void smb_ReleaseVCDbg(smb_vc_t *vcp, char * file, long line)
950 void smb_ReleaseVC(smb_vc_t *vcp)
953 lock_ObtainWrite(&smb_rctLock);
954 osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
955 smb_ReleaseVCInternal(vcp);
956 lock_ReleaseWrite(&smb_rctLock);
959 #ifdef DEBUG_SMB_REFCOUNT
960 void smb_HoldVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
962 void smb_HoldVCNoLock(smb_vc_t *vcp)
965 lock_AssertWrite(&smb_rctLock);
967 #ifdef DEBUG_SMB_REFCOUNT
968 afsi_log("%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
969 osi_Log4(smb_logp,"%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
971 osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
975 #ifdef DEBUG_SMB_REFCOUNT
976 void smb_HoldVCDbg(smb_vc_t *vcp, char * file, long line)
978 void smb_HoldVC(smb_vc_t *vcp)
981 lock_ObtainWrite(&smb_rctLock);
983 #ifdef DEBUG_SMB_REFCOUNT
984 afsi_log("%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
985 osi_Log4(smb_logp,"%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
987 osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
989 lock_ReleaseWrite(&smb_rctLock);
992 void smb_CleanupDeadVC(smb_vc_t *vcp)
1000 smb_user_t *uidpIter;
1001 smb_user_t *uidpNext;
1003 afs_uint32 refCount = 0;
1005 lock_ObtainMutex(&vcp->mx);
1006 if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
1007 lock_ReleaseMutex(&vcp->mx);
1008 osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
1011 vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
1012 lock_ReleaseMutex(&vcp->mx);
1013 osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
1015 lock_ObtainWrite(&smb_rctLock);
1016 /* remove VCP from smb_allVCsp */
1017 for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
1018 if ((*vcpp)->magic != SMB_VC_MAGIC)
1019 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
1020 __FILE__, __LINE__);
1023 vcp->nextp = smb_deadVCsp;
1025 /* Hold onto the reference until we are done with this function */
1030 for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
1031 fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
1033 if (fidpIter->deleteOk)
1036 fid = fidpIter->fid;
1037 osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
1039 smb_HoldFIDNoLock(fidpIter);
1040 lock_ReleaseWrite(&smb_rctLock);
1042 smb_CloseFID(vcp, fidpIter, NULL, 0);
1043 smb_ReleaseFID(fidpIter);
1045 lock_ObtainWrite(&smb_rctLock);
1046 fidpNext = vcp->fidsp;
1049 for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
1050 tidpNext = tidpIter->nextp;
1051 if (tidpIter->deleteOk)
1053 tidpIter->deleteOk = 1;
1055 tid = tidpIter->tid;
1056 osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
1058 smb_HoldTIDNoLock(tidpIter);
1059 smb_ReleaseTID(tidpIter, TRUE);
1060 tidpNext = vcp->tidsp;
1063 for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
1064 uidpNext = uidpIter->nextp;
1065 if (uidpIter->deleteOk)
1067 uidpIter->deleteOk = 1;
1069 /* do not add an additional reference count for the smb_user_t
1070 * as the smb_vc_t already is holding a reference */
1071 lock_ReleaseWrite(&smb_rctLock);
1073 smb_ReleaseUID(uidpIter);
1075 lock_ObtainWrite(&smb_rctLock);
1076 uidpNext = vcp->usersp;
1079 /* The vcp is now on the deadVCsp list. We intentionally drop the
1080 * reference so that the refcount can reach 0 and we can delete it
1082 * If the refCount == 1 going into the ReleaseVCNoLock call
1083 * the object will be freed and it won't be safe to clear
1086 refCount = vcp->refCount;
1087 smb_ReleaseVCNoLock(vcp);
1089 lock_ObtainMutex(&vcp->mx);
1090 vcp->flags &= ~SMB_VCFLAG_CLEAN_IN_PROGRESS;
1091 lock_ReleaseMutex(&vcp->mx);
1094 lock_ReleaseWrite(&smb_rctLock);
1095 osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
1098 #ifdef DEBUG_SMB_REFCOUNT
1099 smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char * file, long line)
1101 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
1106 lock_ObtainWrite(&smb_rctLock);
1108 for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
1109 if (tidp->refCount == 0 && tidp->deleteOk) {
1111 smb_ReleaseTID(tidp, TRUE);
1115 if (tid == tidp->tid) {
1120 if (!tidp && (flags & SMB_FLAG_CREATE)) {
1121 tidp = malloc(sizeof(*tidp));
1122 memset(tidp, 0, sizeof(*tidp));
1123 tidp->nextp = vcp->tidsp;
1126 smb_HoldVCNoLock(vcp);
1128 lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
1131 #ifdef DEBUG_SMB_REFCOUNT
1133 afsi_log("%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1134 osi_Log4(smb_logp,"%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1137 lock_ReleaseWrite(&smb_rctLock);
1141 #ifdef DEBUG_SMB_REFCOUNT
1142 void smb_HoldTIDNoLockDbg(smb_tid_t *tidp, char * file, long line)
1144 void smb_HoldTIDNoLock(smb_tid_t *tidp)
1147 lock_AssertWrite(&smb_rctLock);
1149 #ifdef DEBUG_SMB_REFCOUNT
1150 afsi_log("%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1151 osi_Log4(smb_logp,"%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1155 #ifdef DEBUG_SMB_REFCOUNT
1156 void smb_ReleaseTIDDbg(smb_tid_t *tidp, afs_uint32 locked, char *file, long line)
1158 void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
1163 cm_user_t *userp = NULL;
1164 smb_vc_t *vcp = NULL;
1167 lock_ObtainWrite(&smb_rctLock);
1169 lock_AssertWrite(&smb_rctLock);
1171 osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
1172 #ifdef DEBUG_SMB_REFCOUNT
1173 afsi_log("%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
1174 osi_Log5(smb_logp,"%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
1176 if (tidp->refCount == 0) {
1177 if (tidp->deleteOk) {
1178 ltpp = &tidp->vcp->tidsp;
1179 for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
1183 osi_assertx(tp != NULL, "null smb_tid_t");
1185 lock_FinalizeMutex(&tidp->mx);
1186 userp = tidp->userp; /* remember to drop ref later */
1194 smb_ReleaseVCNoLock(vcp);
1196 lock_ReleaseWrite(&smb_rctLock);
1198 cm_ReleaseUser(userp);
1201 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
1203 smb_user_t *uidp = NULL;
1205 lock_ObtainWrite(&smb_rctLock);
1206 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1207 if (uid == uidp->userID) {
1209 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%S]",
1211 ((uidp->unp)? osi_LogSaveClientString(smb_logp, uidp->unp->name):_C("")));
1215 if (!uidp && (flags & SMB_FLAG_CREATE)) {
1216 uidp = malloc(sizeof(*uidp));
1217 memset(uidp, 0, sizeof(*uidp));
1218 uidp->nextp = vcp->usersp;
1219 uidp->refCount = 2; /* one for the vcp and one for the caller */
1221 smb_HoldVCNoLock(vcp);
1223 lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
1225 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
1227 ((uidp->unp)?osi_LogSaveClientString(smb_logp,uidp->unp->name):_C("")));
1229 lock_ReleaseWrite(&smb_rctLock);
1233 smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
1236 smb_username_t *unp= NULL;
1238 lock_ObtainWrite(&smb_rctLock);
1239 for(unp = usernamesp; unp; unp = unp->nextp) {
1240 if (cm_ClientStrCmpI(unp->name, usern) == 0 &&
1241 cm_ClientStrCmpI(unp->machine, machine) == 0) {
1246 if (!unp && (flags & SMB_FLAG_CREATE)) {
1247 unp = malloc(sizeof(*unp));
1248 memset(unp, 0, sizeof(*unp));
1250 unp->nextp = usernamesp;
1251 unp->name = cm_ClientStrDup(usern);
1252 unp->machine = cm_ClientStrDup(machine);
1254 lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
1255 if (flags & SMB_FLAG_AFSLOGON)
1256 unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
1259 lock_ReleaseWrite(&smb_rctLock);
1263 smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, clientchar_t *usern)
1265 smb_user_t *uidp= NULL;
1267 lock_ObtainWrite(&smb_rctLock);
1268 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1271 if (cm_stricmp_utf16(uidp->unp->name, usern) == 0) {
1273 osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%S]",
1274 vcp,uidp->userID,osi_LogSaveClientString(smb_logp,usern));
1279 lock_ReleaseWrite(&smb_rctLock);
1283 void smb_ReleaseUsername(smb_username_t *unp)
1286 smb_username_t **lupp;
1287 cm_user_t *userp = NULL;
1288 time_t now = osi_Time();
1290 lock_ObtainWrite(&smb_rctLock);
1291 osi_assertx(unp->refCount-- > 0, "smb_username_t refCount 0");
1292 if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
1293 (unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
1295 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1299 osi_assertx(up != NULL, "null smb_username_t");
1301 up->nextp = NULL; /* do not remove this */
1302 lock_FinalizeMutex(&unp->mx);
1308 lock_ReleaseWrite(&smb_rctLock);
1310 cm_ReleaseUser(userp);
1313 void smb_HoldUIDNoLock(smb_user_t *uidp)
1315 lock_AssertWrite(&smb_rctLock);
1319 void smb_ReleaseUID(smb_user_t *uidp)
1323 smb_username_t *unp = NULL;
1325 lock_ObtainWrite(&smb_rctLock);
1326 osi_assertx(uidp->refCount-- > 0, "smb_user_t refCount 0");
1327 if (uidp->refCount == 0) {
1328 lupp = &uidp->vcp->usersp;
1329 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1333 osi_assertx(up != NULL, "null smb_user_t");
1335 lock_FinalizeMutex(&uidp->mx);
1337 smb_ReleaseVCNoLock(uidp->vcp);
1341 lock_ReleaseWrite(&smb_rctLock);
1345 cm_ReleaseUserVCRef(unp->userp);
1346 smb_ReleaseUsername(unp);
1350 cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
1352 cm_user_t *up = NULL;
1357 lock_ObtainMutex(&uidp->mx);
1359 up = uidp->unp->userp;
1362 lock_ReleaseMutex(&uidp->mx);
1368 /* retrieve a held reference to a user structure corresponding to an incoming
1370 * corresponding release function is cm_ReleaseUser.
1372 cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
1375 cm_user_t *up = NULL;
1378 smbp = (smb_t *) inp;
1379 uidp = smb_FindUID(vcp, smbp->uid, 0);
1383 up = smb_GetUserFromUID(uidp);
1385 smb_ReleaseUID(uidp);
1390 * Return a pointer to a pathname extracted from a TID structure. The
1391 * TID structure is not held; assume it won't go away.
1393 long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, clientchar_t ** treepath)
1398 tidp = smb_FindTID(vcp, tid, 0);
1402 if (tidp->flags & SMB_TIDFLAG_IPC) {
1403 code = CM_ERROR_TIDIPC;
1404 /* tidp->pathname would be NULL, but that's fine */
1406 *treepath = tidp->pathname;
1407 smb_ReleaseTID(tidp, FALSE);
1412 /* check to see if we have a chained fid, that is, a fid that comes from an
1413 * OpenAndX message that ran earlier in this packet. In this case, the fid
1414 * field in a read, for example, request, isn't set, since the value is
1415 * supposed to be inherited from the openAndX call.
1417 int smb_ChainFID(int fid, smb_packet_t *inp)
1419 if (inp->fid == 0 || inp->inCount == 0)
1425 /* are we a priv'd user? What does this mean on NT? */
1426 int smb_SUser(cm_user_t *userp)
1431 /* find a file ID. If we pass in 0 we select an unused File ID.
1432 * If the SMB_FLAG_CREATE flag is set, we allocate a new
1433 * smb_fid_t data structure if desired File ID cannot be found.
1435 #ifdef DEBUG_SMB_REFCOUNT
1436 smb_fid_t *smb_FindFIDDbg(smb_vc_t *vcp, unsigned short fid, int flags, char *file, long line)
1438 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
1445 if (!(flags & SMB_FLAG_CREATE))
1450 lock_ObtainWrite(&smb_rctLock);
1452 fid = vcp->fidCounter;
1455 for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
1456 if (fidp->refCount == 0 && fidp->deleteOk) {
1458 lock_ReleaseWrite(&smb_rctLock);
1459 smb_ReleaseFID(fidp);
1460 lock_ObtainWrite(&smb_rctLock);
1462 * We dropped the smb_rctLock so the fid value we are using
1463 * may now be used by another thread. Start over with the
1464 * current vcp->fidCounter.
1467 fid = vcp->fidCounter;
1470 if (fid == fidp->fid) {
1472 osi_Log1(smb_logp, "smb_FindFID New Fid Requested. fid %d found -- retrying ...", fid);
1474 if (fid == 0xFFFF) {
1476 "New FID number wraps on vcp 0x%x", vcp);
1486 if (!fidp && (flags & SMB_FLAG_CREATE)) {
1487 char eventName[MAX_PATH];
1491 osi_Log1(smb_logp, "smb_FindFID New Fid Not Requested, Fid %d Not Found and CREATE flag set.", fid);
1493 osi_Log1(smb_logp, "smb_FindFID New Fid Requested. Creating fid %d", fid);
1495 sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
1496 event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
1497 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
1498 osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
1499 thrd_CloseHandle(event);
1501 if (fid == 0xFFFF) {
1502 osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
1508 fidp = malloc(sizeof(*fidp));
1509 memset(fidp, 0, sizeof(*fidp));
1510 osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
1513 smb_HoldVCNoLock(vcp);
1514 lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
1516 fidp->curr_chunk = fidp->prev_chunk = -2;
1517 fidp->raw_write_event = event;
1519 vcp->fidCounter = fid+1;
1520 if (vcp->fidCounter == 0xFFFF) {
1521 osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
1523 vcp->fidCounter = 1;
1528 #ifdef DEBUG_SMB_REFCOUNT
1530 afsi_log("%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1531 osi_Log4(smb_logp,"%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1534 lock_ReleaseWrite(&smb_rctLock);
1539 /* Must not be called with scp->rw held because smb_ReleaseFID might be called */
1540 #ifdef DEBUG_SMB_REFCOUNT
1541 smb_fid_t *smb_FindFIDByScacheDbg(smb_vc_t *vcp, cm_scache_t * scp, char *file, long line)
1543 smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
1546 smb_fid_t *fidp = NULL, *nextp = NULL;
1552 * If the fidp->scp changes out from under us then
1553 * we must not grab a refCount. It means the *fidp
1554 * was processed by smb_CloseFID() and the *fidp is
1555 * no longer valid for use.
1557 lock_ObtainWrite(&smb_rctLock);
1558 for(fidp = vcp->fidsp, (fidp ? fidp->refCount++ : 0); fidp; fidp = nextp, nextp = NULL) {
1559 nextp = (smb_fid_t *) osi_QNext(&fidp->q);
1563 if (scp == fidp->scp) {
1564 lock_ReleaseWrite(&smb_rctLock);
1565 lock_ObtainMutex(&fidp->mx);
1566 lock_ObtainWrite(&smb_rctLock);
1567 if (scp == fidp->scp) {
1568 lock_ReleaseMutex(&fidp->mx);
1571 lock_ReleaseMutex(&fidp->mx);
1574 if (fidp->refCount > 1) {
1577 lock_ReleaseWrite(&smb_rctLock);
1578 smb_ReleaseFID(fidp);
1579 lock_ObtainWrite(&smb_rctLock);
1584 if (nextp->refCount > 1) {
1587 lock_ReleaseWrite(&smb_rctLock);
1588 smb_ReleaseFID(nextp);
1589 lock_ObtainWrite(&smb_rctLock);
1593 #ifdef DEBUG_SMB_REFCOUNT
1595 afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1596 osi_Log4(smb_logp,"%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1599 lock_ReleaseWrite(&smb_rctLock);
1603 #ifdef DEBUG_SMB_REFCOUNT
1604 void smb_HoldFIDNoLockDbg(smb_fid_t *fidp, char *file, long line)
1606 void smb_HoldFIDNoLock(smb_fid_t *fidp)
1609 lock_AssertWrite(&smb_rctLock);
1611 #ifdef DEBUG_SMB_REFCOUNT
1612 afsi_log("%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1613 osi_Log4(smb_logp,"%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1618 /* smb_ReleaseFID cannot be called while a cm_scache_t rwlock is held */
1619 /* the smb_fid_t->mx and smb_rctLock must not be held */
1620 #ifdef DEBUG_SMB_REFCOUNT
1621 void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
1623 void smb_ReleaseFID(smb_fid_t *fidp)
1626 cm_scache_t *scp = NULL;
1627 cm_user_t *userp = NULL;
1628 smb_vc_t *vcp = NULL;
1629 smb_ioctl_t *ioctlp;
1631 lock_ObtainMutex(&fidp->mx);
1632 lock_ObtainWrite(&smb_rctLock);
1633 osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
1634 #ifdef DEBUG_SMB_REFCOUNT
1635 afsi_log("%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
1636 osi_Log5(smb_logp,"%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
1638 if (fidp->refCount == 0) {
1639 if (fidp->deleteOk) {
1642 scp = fidp->scp; /* release after lock is released */
1644 lock_ObtainWrite(&scp->rw);
1645 scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
1646 lock_ReleaseWrite(&scp->rw);
1647 osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
1650 userp = fidp->userp;
1654 osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
1655 thrd_CloseHandle(fidp->raw_write_event);
1657 /* and see if there is ioctl stuff to free */
1658 ioctlp = fidp->ioctlp;
1661 cm_FreeSpace(ioctlp->prefix);
1662 if (ioctlp->ioctl.inAllocp)
1663 free(ioctlp->ioctl.inAllocp);
1664 if (ioctlp->ioctl.outAllocp)
1665 free(ioctlp->ioctl.outAllocp);
1669 smb_CleanupRPCFid(fidp);
1671 lock_ReleaseMutex(&fidp->mx);
1672 lock_FinalizeMutex(&fidp->mx);
1677 smb_ReleaseVCNoLock(vcp);
1681 lock_ReleaseMutex(&fidp->mx);
1683 lock_ReleaseWrite(&smb_rctLock);
1685 /* now release the scache structure */
1687 cm_ReleaseSCache(scp);
1690 cm_ReleaseUser(userp);
1694 * Case-insensitive search for one string in another;
1695 * used to find variable names in submount pathnames.
1697 static clientchar_t *smb_stristr(clientchar_t *str1, clientchar_t *str2)
1699 clientchar_t *cursor;
1701 for (cursor = str1; *cursor; cursor++)
1702 if (cm_ClientStrCmpI(cursor, str2) == 0)
1709 * Substitute a variable value for its name in a submount pathname. Variable
1710 * name has been identified by smb_stristr() and is in substr. Variable name
1711 * length (plus one) is in substr_size. Variable value is in newstr.
1713 static void smb_subst(clientchar_t *str1, int cchstr1, clientchar_t *substr,
1714 unsigned int substr_size, clientchar_t *newstr)
1716 clientchar_t temp[1024];
1718 cm_ClientStrCpy(temp, lengthof(temp), substr + substr_size - 1);
1719 cm_ClientStrCpy(substr, cchstr1 - (substr - str1), newstr);
1720 cm_ClientStrCat(str1, cchstr1, temp);
1723 clientchar_t VNUserName[] = _C("%USERNAME%");
1724 clientchar_t VNLCUserName[] = _C("%LCUSERNAME%");
1725 clientchar_t VNComputerName[] = _C("%COMPUTERNAME%");
1726 clientchar_t VNLCComputerName[] = _C("%LCCOMPUTERNAME%");
1728 typedef struct smb_findShare_rock {
1729 clientchar_t * shareName;
1730 clientchar_t * match;
1732 } smb_findShare_rock_t;
1734 #define SMB_FINDSHARE_EXACT_MATCH 1
1735 #define SMB_FINDSHARE_PARTIAL_MATCH 2
1737 long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
1741 smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
1742 normchar_t normName[MAX_PATH];
1744 if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0])) == 0) {
1745 osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
1746 osi_LogSaveString(smb_logp, dep->name));
1750 if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
1751 if(!cm_ClientStrCmpI(normName, vrock->shareName))
1752 matchType = SMB_FINDSHARE_EXACT_MATCH;
1754 matchType = SMB_FINDSHARE_PARTIAL_MATCH;
1757 vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
1758 vrock->matchType = matchType;
1760 if(matchType == SMB_FINDSHARE_EXACT_MATCH)
1761 return CM_ERROR_STOPNOW;
1767 /* find a shareName in the table of submounts */
1768 int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
1769 clientchar_t *shareName,
1770 clientchar_t **pathNamep)
1774 clientchar_t pathName[1024];
1777 clientchar_t *p, *q;
1778 fschar_t *cellname = NULL;
1781 DWORD allSubmount = 1;
1783 /* if allSubmounts == 0, only return the //mountRoot/all share
1784 * if in fact it has been been created in the subMounts table.
1785 * This is to allow sites that want to restrict access to the
1788 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1789 0, KEY_QUERY_VALUE, &parmKey);
1790 if (code == ERROR_SUCCESS) {
1791 cblen = sizeof(allSubmount);
1792 code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
1793 (BYTE *) &allSubmount, &cblen);
1794 if (code != ERROR_SUCCESS) {
1797 RegCloseKey (parmKey);
1800 if (allSubmount && cm_ClientStrCmpI(shareName, _C("all")) == 0) {
1805 /* In case, the all share is disabled we need to still be able
1806 * to handle ioctl requests
1808 if (cm_ClientStrCmpI(shareName, _C("ioctl$")) == 0) {
1809 *pathNamep = cm_ClientStrDup(_C("/.__ioctl__"));
1813 if (MSRPC_IsWellKnownService(shareName) ||
1814 cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
1815 cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
1821 /* Check for volume references
1823 * They look like <cell>{%,#}<volume>
1825 if (cm_ClientStrChr(shareName, '%') != NULL ||
1826 cm_ClientStrChr(shareName, '#') != NULL) {
1827 clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
1828 /* make room for '/@vol:' + mountchar + NULL terminator*/
1830 osi_Log1(smb_logp, "smb_FindShare found volume reference [%S]",
1831 osi_LogSaveClientString(smb_logp, shareName));
1833 cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
1834 _C("/") _C(CM_PREFIX_VOL) _C("%s"), shareName);
1835 cchlen = (DWORD)(cm_ClientStrLen(pathstr) + 1);
1837 *pathNamep = malloc(cchlen * sizeof(clientchar_t));
1839 cm_ClientStrCpy(*pathNamep, cchlen, pathstr);
1840 cm_ClientStrLwr(*pathNamep);
1841 osi_Log1(smb_logp, " returning pathname [%S]",
1842 osi_LogSaveClientString(smb_logp, *pathNamep));
1850 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
1851 0, KEY_QUERY_VALUE, &parmKey);
1852 if (code == ERROR_SUCCESS) {
1853 cblen = sizeof(pathName);
1854 code = RegQueryValueExW(parmKey, shareName, NULL, NULL,
1855 (BYTE *) pathName, &cblen);
1856 if (code != ERROR_SUCCESS)
1858 RegCloseKey (parmKey);
1862 cchlen = cblen / sizeof(clientchar_t);
1863 if (cchlen != 0 && cchlen != lengthof(pathName) - 1) {
1864 /* We can accept either unix or PC style AFS pathnames. Convert
1865 * Unix-style to PC style here for internal use.
1868 cchlen = lengthof(pathName);
1870 /* within this code block, we maintain, cchlen = writeable
1871 buffer length of p */
1873 if (cm_ClientStrCmpN(p, cm_mountRootC, cm_mountRootCLen) == 0) {
1874 p += cm_mountRootCLen; /* skip mount path */
1875 cchlen -= (DWORD)(p - pathName);
1880 if (*q == _C('/')) *q = _C('\\'); /* change to \ */
1886 clientchar_t temp[1024];
1888 if (var = smb_stristr(p, VNUserName)) {
1889 if (uidp && uidp->unp)
1890 smb_subst(p, cchlen, var, lengthof(VNUserName),uidp->unp->name);
1892 smb_subst(p, cchlen, var, lengthof(VNUserName), _C(" "));
1894 else if (var = smb_stristr(p, VNLCUserName))
1896 if (uidp && uidp->unp)
1897 cm_ClientStrCpy(temp, lengthof(temp), uidp->unp->name);
1899 cm_ClientStrCpy(temp, lengthof(temp), _C(" "));
1900 cm_ClientStrLwr(temp);
1901 smb_subst(p, cchlen, var, lengthof(VNLCUserName), temp);
1903 else if (var = smb_stristr(p, VNComputerName))
1905 sizeTemp = lengthof(temp);
1906 GetComputerNameW(temp, &sizeTemp);
1907 smb_subst(p, cchlen, var, lengthof(VNComputerName), temp);
1909 else if (var = smb_stristr(p, VNLCComputerName))
1911 sizeTemp = lengthof(temp);
1912 GetComputerName((LPTSTR)temp, &sizeTemp);
1913 cm_ClientStrLwr(temp);
1914 smb_subst(p, cchlen, var, lengthof(VNLCComputerName), temp);
1919 *pathNamep = cm_ClientStrDup(p);
1924 /* First lookup shareName in root.afs */
1926 smb_findShare_rock_t vrock;
1928 fschar_t ftemp[1024];
1929 clientchar_t * p = shareName;
1932 /* attempt to locate a partial match in root.afs. This is because
1933 when using the ANSI RAP calls, the share name is limited to 13 chars
1934 and hence is truncated. Of course we prefer exact matches. */
1936 thyper.HighPart = 0;
1939 vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
1940 if (vrock.shareName == NULL)
1943 vrock.matchType = 0;
1945 cm_HoldSCache(cm_data.rootSCachep);
1946 code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
1947 (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
1948 cm_ReleaseSCache(cm_data.rootSCachep);
1950 free(vrock.shareName);
1951 vrock.shareName = NULL;
1953 if (vrock.matchType) {
1954 cm_ClientStrPrintfN(pathName, lengthof(pathName), _C("/%s/"), vrock.match);
1955 *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
1960 /* if we get here, there was no match for the share in root.afs */
1961 /* so try to create \\<netbiosName>\<cellname> */
1966 /* Get the full name for this cell */
1967 cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
1968 code = cm_SearchCellRegistry(1, cellname, ftemp, 0, 0, 0);
1969 if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
1970 code = cm_SearchCellFile(cellname, ftemp, 0, 0);
1971 if (code && cm_dnsEnabled) {
1973 code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
1978 /* construct the path */
1980 clientchar_t temp[1024];
1982 if (cm_FsStringToClientString(ftemp, -1, temp, 1024) != 0) {
1983 cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
1984 rw ? _C("/.%S/") : _C("/%S/"), temp);
1985 *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
1995 /* Client-side offline caching policy types */
1996 #define CSC_POLICY_MANUAL 0
1997 #define CSC_POLICY_DOCUMENTS 1
1998 #define CSC_POLICY_PROGRAMS 2
1999 #define CSC_POLICY_DISABLE 3
2001 int smb_FindShareCSCPolicy(clientchar_t *shareName)
2004 clientchar_t policy[1024];
2007 int retval = CSC_POLICY_MANUAL;
2009 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2010 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
2013 REG_OPTION_NON_VOLATILE,
2017 NULL ) != ERROR_SUCCESS)
2018 retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
2020 len = sizeof(policy);
2021 if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
2023 retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
2025 else if (cm_ClientStrCmpIA(policy, _C("manual")) == 0)
2027 retval = CSC_POLICY_MANUAL;
2029 else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
2031 retval = CSC_POLICY_DOCUMENTS;
2033 else if (cm_ClientStrCmpIA(policy, _C("programs")) == 0)
2035 retval = CSC_POLICY_PROGRAMS;
2037 else if (cm_ClientStrCmpIA(policy, _C("disable")) == 0)
2039 retval = CSC_POLICY_DISABLE;
2042 RegCloseKey(hkCSCPolicy);
2046 /* find a dir search structure by cookie value, and return it held.
2047 * Must be called with smb_globalLock held.
2049 smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
2051 smb_dirSearch_t *dsp;
2053 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
2054 if (dsp->cookie == cookie) {
2055 if (dsp != smb_firstDirSearchp) {
2056 /* move to head of LRU queue, too, if we're not already there */
2057 if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
2058 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
2059 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2060 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2061 if (!smb_lastDirSearchp)
2062 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
2070 osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
2071 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
2072 osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
2078 void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
2080 lock_ObtainMutex(&dsp->mx);
2081 osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p",
2082 dsp->cookie, dsp, dsp->scp);
2083 dsp->flags |= SMB_DIRSEARCH_DELETE;
2084 if (dsp->scp != NULL) {
2085 lock_ObtainWrite(&dsp->scp->rw);
2086 if (dsp->flags & SMB_DIRSEARCH_BULKST) {
2087 dsp->flags &= ~SMB_DIRSEARCH_BULKST;
2088 dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
2089 dsp->scp->bulkStatProgress = hzero;
2091 lock_ReleaseWrite(&dsp->scp->rw);
2093 lock_ReleaseMutex(&dsp->mx);
2096 /* Must be called with the smb_globalLock held */
2097 void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
2099 cm_scache_t *scp = NULL;
2101 osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
2102 if (dsp->refCount == 0) {
2103 lock_ObtainMutex(&dsp->mx);
2104 if (dsp->flags & SMB_DIRSEARCH_DELETE) {
2105 if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
2106 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
2107 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2108 lock_ReleaseMutex(&dsp->mx);
2109 lock_FinalizeMutex(&dsp->mx);
2111 osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
2112 dsp->cookie, dsp, scp);
2115 lock_ReleaseMutex(&dsp->mx);
2118 /* do this now to avoid spurious locking hierarchy creation */
2120 cm_ReleaseSCache(scp);
2123 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
2125 lock_ObtainWrite(&smb_globalLock);
2126 smb_ReleaseDirSearchNoLock(dsp);
2127 lock_ReleaseWrite(&smb_globalLock);
2130 /* find a dir search structure by cookie value, and return it held */
2131 smb_dirSearch_t *smb_FindDirSearch(long cookie)
2133 smb_dirSearch_t *dsp;
2135 lock_ObtainWrite(&smb_globalLock);
2136 dsp = smb_FindDirSearchNoLock(cookie);
2137 lock_ReleaseWrite(&smb_globalLock);
2141 /* GC some dir search entries, in the address space expected by the specific protocol.
2142 * Must be called with smb_globalLock held; release the lock temporarily.
2144 #define SMB_DIRSEARCH_GCMAX 10 /* how many at once */
2145 void smb_GCDirSearches(int isV3)
2147 smb_dirSearch_t *prevp;
2148 smb_dirSearch_t *dsp;
2149 smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
2153 victimCount = 0; /* how many have we got so far */
2154 for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
2155 /* we'll move tp from queue, so
2158 prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
2159 /* if no one is using this guy, and we're either in the new protocol,
2160 * or we're in the old one and this is a small enough ID to be useful
2161 * to the old protocol, GC this guy.
2163 if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
2164 /* hold and delete */
2165 lock_ObtainMutex(&dsp->mx);
2166 dsp->flags |= SMB_DIRSEARCH_DELETE;
2167 lock_ReleaseMutex(&dsp->mx);
2168 victimsp[victimCount++] = dsp;
2172 /* don't do more than this */
2173 if (victimCount >= SMB_DIRSEARCH_GCMAX)
2177 /* now release them */
2178 for (i = 0; i < victimCount; i++) {
2179 smb_ReleaseDirSearchNoLock(victimsp[i]);
2183 /* function for allocating a dir search entry. We need these to remember enough context
2184 * since we don't get passed the path from call to call during a directory search.
2186 * Returns a held dir search structure, and bumps the reference count on the vnode,
2187 * since it saves a pointer to the vnode.
2189 smb_dirSearch_t *smb_NewDirSearch(int isV3)
2191 smb_dirSearch_t *dsp;
2197 lock_ObtainWrite(&smb_globalLock);
2200 /* what's the biggest ID allowed in this version of the protocol */
2201 /* TODO: do we really want a non v3 dir search request to wrap
2202 smb_dirSearchCounter? */
2203 maxAllowed = isV3 ? 65535 : 255;
2204 if (smb_dirSearchCounter > maxAllowed)
2205 smb_dirSearchCounter = 1;
2207 start = smb_dirSearchCounter;
2210 /* twice so we have enough tries to find guys we GC after one pass;
2211 * 10 extra is just in case I mis-counted.
2213 if (++counter > 2*maxAllowed+10)
2214 osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
2216 if (smb_dirSearchCounter > maxAllowed) {
2217 smb_dirSearchCounter = 1;
2219 if (smb_dirSearchCounter == start) {
2221 smb_GCDirSearches(isV3);
2224 dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
2226 /* don't need to watch for refcount zero and deleted, since
2227 * we haven't dropped the global lock.
2230 ++smb_dirSearchCounter;
2234 dsp = malloc(sizeof(*dsp));
2235 memset(dsp, 0, sizeof(*dsp));
2236 dsp->cookie = smb_dirSearchCounter;
2237 ++smb_dirSearchCounter;
2239 lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
2240 dsp->lastTime = osi_Time();
2241 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2242 if (!smb_lastDirSearchp)
2243 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
2245 osi_Log2(smb_logp,"smb_NewDirSearch cookie %d dsp 0x%p",
2249 lock_ReleaseWrite(&smb_globalLock);
2253 static smb_packet_t *smb_GetPacket(void)
2257 lock_ObtainWrite(&smb_globalLock);
2258 tbp = smb_packetFreeListp;
2260 smb_packetFreeListp = tbp->nextp;
2261 lock_ReleaseWrite(&smb_globalLock);
2263 tbp = calloc(sizeof(*tbp),1);
2264 tbp->magic = SMB_PACKETMAGIC;
2267 tbp->resumeCode = 0;
2273 tbp->ncb_length = 0;
2276 tbp->stringsp = NULL;
2278 osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
2283 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
2286 tbp = smb_GetPacket();
2287 memcpy(tbp, pkt, sizeof(smb_packet_t));
2288 tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
2289 tbp->stringsp = NULL;
2291 smb_HoldVC(tbp->vcp);
2295 static NCB *smb_GetNCB(void)
2300 lock_ObtainWrite(&smb_globalLock);
2301 tbp = smb_ncbFreeListp;
2303 smb_ncbFreeListp = tbp->nextp;
2304 lock_ReleaseWrite(&smb_globalLock);
2306 tbp = calloc(sizeof(*tbp),1);
2307 tbp->magic = SMB_NCBMAGIC;
2310 osi_assertx(tbp->magic == SMB_NCBMAGIC, "invalid smb_packet_t magic");
2312 memset(&tbp->ncb, 0, sizeof(NCB));
2317 static void FreeSMBStrings(smb_packet_t * pkt)
2322 for (s = pkt->stringsp; s; s = ns) {
2326 pkt->stringsp = NULL;
2329 void smb_FreePacket(smb_packet_t *tbp)
2331 smb_vc_t * vcp = NULL;
2332 osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
2334 lock_ObtainWrite(&smb_globalLock);
2335 tbp->nextp = smb_packetFreeListp;
2336 smb_packetFreeListp = tbp;
2337 tbp->magic = SMB_PACKETMAGIC;
2341 tbp->resumeCode = 0;
2347 tbp->ncb_length = 0;
2349 FreeSMBStrings(tbp);
2350 lock_ReleaseWrite(&smb_globalLock);
2356 static void smb_FreeNCB(NCB *bufferp)
2360 tbp = (smb_ncb_t *) bufferp;
2361 osi_assertx(tbp->magic == SMB_NCBMAGIC, "invalid smb_packet_t magic");
2363 lock_ObtainWrite(&smb_globalLock);
2364 tbp->nextp = smb_ncbFreeListp;
2365 smb_ncbFreeListp = tbp;
2366 lock_ReleaseWrite(&smb_globalLock);
2369 /* get a ptr to the data part of a packet, and its count */
2370 unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
2374 unsigned char *afterParmsp;
2376 parmBytes = *smbp->wctp << 1;
2377 afterParmsp = smbp->wctp + parmBytes + 1;
2379 dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
2380 if (nbytesp) *nbytesp = dataBytes;
2382 /* don't forget to skip the data byte count, since it follows
2383 * the parameters; that's where the "2" comes from below.
2385 return (unsigned char *) (afterParmsp + 2);
2388 /* must set all the returned parameters before playing around with the
2389 * data region, since the data region is located past the end of the
2390 * variable number of parameters.
2392 void smb_SetSMBDataLength(smb_packet_t *smbp, unsigned int dsize)
2394 unsigned char *afterParmsp;
2396 afterParmsp = smbp->wctp + ((*smbp->wctp)<<1) + 1;
2398 *afterParmsp++ = dsize & 0xff;
2399 *afterParmsp = (dsize>>8) & 0xff;
2402 /* return the parm'th parameter in the smbp packet */
2403 unsigned short smb_GetSMBParm(smb_packet_t *smbp, int parm)
2406 unsigned char *parmDatap;
2408 parmCount = *smbp->wctp;
2410 if (parm >= parmCount) {
2413 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2414 parm, parmCount, smbp->ncb_length);
2415 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2416 parm, parmCount, smbp->ncb_length);
2417 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2418 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2419 osi_panic(s, __FILE__, __LINE__);
2421 parmDatap = smbp->wctp + (2*parm) + 1;
2423 return parmDatap[0] + (parmDatap[1] << 8);
2426 /* return the parm'th parameter in the smbp packet */
2427 unsigned char smb_GetSMBParmByte(smb_packet_t *smbp, int parm)
2430 unsigned char *parmDatap;
2432 parmCount = *smbp->wctp;
2434 if (parm >= parmCount) {
2437 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2438 parm, parmCount, smbp->ncb_length);
2439 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2440 parm, parmCount, smbp->ncb_length);
2441 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2442 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2443 osi_panic(s, __FILE__, __LINE__);
2445 parmDatap = smbp->wctp + (2*parm) + 1;
2447 return parmDatap[0];
2450 /* return the parm'th parameter in the smbp packet */
2451 unsigned int smb_GetSMBParmLong(smb_packet_t *smbp, int parm)
2454 unsigned char *parmDatap;
2456 parmCount = *smbp->wctp;
2458 if (parm + 1 >= parmCount) {
2461 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2462 parm, parmCount, smbp->ncb_length);
2463 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2464 parm, parmCount, smbp->ncb_length);
2465 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2466 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2467 osi_panic(s, __FILE__, __LINE__);
2469 parmDatap = smbp->wctp + (2*parm) + 1;
2471 return parmDatap[0] + (parmDatap[1] << 8) + (parmDatap[2] << 16) + (parmDatap[3] << 24);
2474 /* return the parm'th parameter in the smbp packet */
2475 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
2478 unsigned char *parmDatap;
2480 parmCount = *smbp->wctp;
2482 if (parm * 2 + offset >= parmCount * 2) {
2485 sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
2486 parm, offset, parmCount, smbp->ncb_length);
2487 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET,
2488 __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
2489 osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
2490 parm, offset, parmCount, smbp->ncb_length);
2491 osi_panic(s, __FILE__, __LINE__);
2493 parmDatap = smbp->wctp + (2*parm) + 1 + offset;
2495 return parmDatap[0] + (parmDatap[1] << 8);
2498 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
2500 unsigned char *parmDatap;
2502 /* make sure we have enough slots */
2503 if (*smbp->wctp <= slot)
2504 *smbp->wctp = slot+1;
2506 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2507 *parmDatap++ = parmValue & 0xff;
2508 *parmDatap = (parmValue>>8) & 0xff;
2511 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
2513 unsigned char *parmDatap;
2515 /* make sure we have enough slots */
2516 if (*smbp->wctp <= slot)
2517 *smbp->wctp = slot+2;
2519 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2520 *parmDatap++ = parmValue & 0xff;
2521 *parmDatap++ = (parmValue>>8) & 0xff;
2522 *parmDatap++ = (parmValue>>16) & 0xff;
2523 *parmDatap = (parmValue>>24) & 0xff;
2526 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
2528 unsigned char *parmDatap;
2531 /* make sure we have enough slots */
2532 if (*smbp->wctp <= slot)
2533 *smbp->wctp = slot+4;
2535 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2537 *parmDatap++ = *parmValuep++;
2540 void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
2542 unsigned char *parmDatap;
2544 /* make sure we have enough slots */
2545 if (*smbp->wctp <= slot) {
2546 if (smbp->oddByte) {
2548 *smbp->wctp = slot+1;
2553 parmDatap = smbp->wctp + 2*slot + 1 + (1 - smbp->oddByte);
2554 *parmDatap++ = parmValue & 0xff;
2559 void smb_StripLastComponent(clientchar_t *outPathp, clientchar_t **lastComponentp,
2560 clientchar_t *inPathp)
2562 clientchar_t *lastSlashp;
2563 clientchar_t *streamp = NULL;
2564 clientchar_t *typep = NULL;
2566 lastSlashp = cm_ClientStrRChr(inPathp, '\\');
2567 if (lastComponentp) {
2568 *lastComponentp = lastSlashp;
2572 * If the name contains a stream name and a type
2573 * and the stream name is the nul-string and the
2574 * type is $DATA, then strip "::$DATA" from the
2575 * last component string that is returned.
2577 * Otherwise, return the full path name and allow
2578 * the file name to be rejected because it contains
2581 typep = cm_ClientStrRChr(lastSlashp, L':');
2582 if (typep && cm_ClientStrCmpI(typep, L":$DATA") == 0) {
2584 streamp = cm_ClientStrRChr(lastSlashp, L':');
2585 if (streamp && cm_ClientStrCmpI(streamp, L":") == 0) {
2589 osi_Log2(smb_logp, "smb_StripLastComponent found stream [%S] type [%S]",
2590 osi_LogSaveClientString(smb_logp,streamp),
2591 osi_LogSaveClientString(smb_logp,typep));
2595 if (inPathp == lastSlashp)
2597 *outPathp++ = *inPathp++;
2606 clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
2607 char **chainpp, int flags)
2610 afs_uint32 type = *inp++;
2613 * The first byte specifies the type of the input string.
2614 * CIFS TR 1.0 3.2.10. This function only parses null terminated
2618 /* Length Counted */
2619 case 0x1: /* Data Block */
2620 case 0x5: /* Variable Block */
2621 cb = *inp++ << 16 | *inp++;
2624 /* Null-terminated string */
2625 case 0x4: /* ASCII */
2626 case 0x3: /* Pathname */
2627 case 0x2: /* Dialect */
2628 cb = sizeof(pktp->data) - (inp - pktp->data);
2629 if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
2630 #ifdef DEBUG_UNICODE
2633 cb = sizeof(pktp->data);
2638 return NULL; /* invalid input */
2642 if (type == 0x2 /* Dialect */ || !WANTS_UNICODE(pktp))
2643 flags |= SMB_STRF_FORCEASCII;
2646 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2649 clientchar_t *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
2650 char ** chainpp, int flags)
2655 if (!WANTS_UNICODE(pktp))
2656 flags |= SMB_STRF_FORCEASCII;
2659 cb = sizeof(pktp->data) - (inp - pktp->data);
2660 if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
2661 #ifdef DEBUG_UNICODE
2664 cb = sizeof(pktp->data);
2666 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
2667 flags | SMB_STRF_SRCNULTERM);
2670 clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
2671 size_t cb, char ** chainpp, int flags)
2674 if (!WANTS_UNICODE(pktp))
2675 flags |= SMB_STRF_FORCEASCII;
2678 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2681 clientchar_t *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp,
2682 size_t cch, char ** chainpp, int flags)
2687 if (!WANTS_UNICODE(pktp))
2688 flags |= SMB_STRF_FORCEASCII;
2690 cb = cch * sizeof(wchar_t);
2693 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2697 smb_ParseStringBuf(const unsigned char * bufbase,
2698 cm_space_t ** stringspp,
2699 unsigned char *inp, size_t *pcb_max,
2700 char **chainpp, int flags)
2703 if (!(flags & SMB_STRF_FORCEASCII)) {
2705 cm_space_t * spacep;
2708 if (bufbase && ((inp - bufbase) % 2) != 0) {
2709 inp++; /* unicode strings are always word aligned */
2713 if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t),
2715 cch_src = *pcb_max / sizeof(wchar_t);
2719 *pcb_max -= (cch_src + 1) * sizeof(wchar_t);
2726 spacep = cm_GetSpace();
2727 spacep->nextp = *stringspp;
2728 *stringspp = spacep;
2732 *chainpp = inp + sizeof(wchar_t);
2735 *(spacep->wdata) = 0;
2736 return spacep->wdata;
2739 StringCchCopyNW(spacep->wdata,
2740 lengthof(spacep->wdata),
2741 (const clientchar_t *) inp, cch_src);
2744 *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t);
2746 return spacep->wdata;
2750 cm_space_t * spacep;
2753 /* Not using Unicode */
2755 *chainpp = inp + strlen(inp) + 1;
2758 spacep = cm_GetSpace();
2759 spacep->nextp = *stringspp;
2760 *stringspp = spacep;
2762 cchdest = lengthof(spacep->wdata);
2763 cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
2764 spacep->wdata, cchdest);
2766 return spacep->wdata;
2772 unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
2774 size_t * plen, int flags)
2780 /* we are only calculating the required size */
2787 if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
2789 StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
2790 if (!(flags & SMB_STRF_IGNORENUL))
2791 *plen += sizeof(wchar_t);
2793 return (unsigned char *) 1; /* return TRUE if we are using unicode */
2803 cch_str = cm_ClientStrLen(str);
2804 cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
2807 *plen = ((flags & SMB_STRF_IGNORENUL)? cch_dest: cch_dest+1);
2815 /* if outp != NULL ... */
2817 /* Number of bytes left in the buffer.
2819 If outp lies inside the packet data buffer, we assume that the
2820 buffer is the packet data buffer. Otherwise we assume that the
2821 buffer is sizeof(packet->data).
2824 if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
2825 align = (int)((outp - pktp->data) % 2);
2826 buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
2828 align = (int)(((size_t) outp) % 2);
2829 buffersize = (int)sizeof(pktp->data);
2834 if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
2840 if (*str == _C('\0')) {
2842 if (buffersize < sizeof(wchar_t))
2845 *((wchar_t *) outp) = L'\0';
2846 if (plen && !(flags & SMB_STRF_IGNORENUL))
2847 *plen += sizeof(wchar_t);
2848 return outp + sizeof(wchar_t);
2851 nchars = cm_ClientStringToUtf16(str, -1, (wchar_t *) outp, (int)(buffersize / sizeof(wchar_t)));
2853 osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
2854 osi_LogSaveClientString(smb_logp, str),
2860 *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENUL)? nchars - 1: nchars);
2862 return outp + sizeof(wchar_t) * nchars;
2870 cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
2873 *plen += ((flags & SMB_STRF_IGNORENUL)? cch_dest - 1: cch_dest);
2875 return outp + cch_dest;
2879 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
2885 tlen = inp[0] + (inp[1]<<8);
2886 inp += 2; /* skip length field */
2889 *chainpp = inp + tlen;
2898 unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
2902 if (*inp++ != 0x1) return NULL;
2903 tlen = inp[0] + (inp[1]<<8);
2904 inp += 2; /* skip length field */
2907 *chainpp = inp + tlen;
2910 if (lengthp) *lengthp = tlen;
2915 /* format a packet as a response */
2916 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
2921 outp = (smb_t *) op;
2923 /* zero the basic structure through the smb_wct field, and zero the data
2924 * size field, assuming that wct stays zero; otherwise, you have to
2925 * explicitly set the data size field, too.
2927 inSmbp = (smb_t *) inp;
2928 memset(outp, 0, sizeof(smb_t)+2);
2934 outp->com = inSmbp->com;
2935 outp->tid = inSmbp->tid;
2936 outp->pid = inSmbp->pid;
2937 outp->uid = inSmbp->uid;
2938 outp->mid = inSmbp->mid;
2939 outp->res[0] = inSmbp->res[0];
2940 outp->res[1] = inSmbp->res[1];
2941 op->inCom = inSmbp->com;
2943 outp->reb = SMB_FLAGS_SERVER_TO_CLIENT;
2944 #ifdef SEND_CANONICAL_PATHNAMES
2945 outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
2947 outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
2949 if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
2950 outp->flg2 |= SMB_FLAGS2_UNICODE;
2953 /* copy fields in generic packet area */
2954 op->wctp = &outp->wct;
2957 /* send a (probably response) packet; vcp tells us to whom to send it.
2958 * we compute the length by looking at wct and bcc fields.
2960 void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
2970 ncbp = smb_GetNCB();
2974 memset(ncbp, 0, sizeof(NCB));
2976 extra = 2 * (*inp->wctp); /* space used by parms, in bytes */
2977 tp = inp->wctp + 1+ extra; /* points to count of data bytes */
2978 extra += tp[0] + (tp[1]<<8);
2979 extra += (unsigned int)(inp->wctp - inp->data); /* distance to last wct field */
2980 extra += 3; /* wct and length fields */
2982 ncbp->ncb_length = extra; /* bytes to send */
2983 ncbp->ncb_lsn = (unsigned char) vcp->lsn; /* vc to use */
2984 ncbp->ncb_lana_num = vcp->lana;
2985 ncbp->ncb_command = NCBSEND; /* op means send data */
2986 ncbp->ncb_buffer = (char *) inp;/* packet */
2987 code = Netbios(ncbp);
2990 const char * s = ncb_error_string(code);
2991 osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
2992 LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
2994 lock_ObtainMutex(&vcp->mx);
2995 if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
2996 osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
2998 vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
2999 lock_ReleaseMutex(&vcp->mx);
3000 lock_ObtainWrite(&smb_globalLock);
3001 dead_sessions[vcp->session] = TRUE;
3002 lock_ReleaseWrite(&smb_globalLock);
3003 smb_CleanupDeadVC(vcp);
3005 lock_ReleaseMutex(&vcp->mx);
3013 void smb_MapNTError(long code, unsigned long *NTStatusp)
3015 unsigned long NTStatus;
3017 /* map CM_ERROR_* errors to NT 32-bit status codes */
3018 /* NT Status codes are listed in ntstatus.h not winerror.h */
3022 else if (code == CM_ERROR_NOSUCHCELL) {
3023 NTStatus = 0xC0000034L; /* Name not found */
3025 else if (code == CM_ERROR_NOSUCHVOLUME) {
3026 NTStatus = 0xC0000034L; /* Name not found */
3028 else if (code == CM_ERROR_TIMEDOUT) {
3030 NTStatus = 0xC00000CFL; /* Sharing Paused */
3032 /* Do not send Timeout to the SMB redirector.
3033 * It causes the redirector to drop the connection */
3034 NTStatus = 0x00000102L; /* Timeout */
3035 /* do not send Retry to the SMB redirector.
3036 * It believes the error comes from the transport
3037 * layer not from the SMB server. */
3038 NTStatus = 0xC000022DL; /* Retry */
3040 NTStatus = 0xC00000B5L; /* I/O Timeout */
3043 else if (code == CM_ERROR_RETRY) {
3045 NTStatus = 0xC000022DL; /* Retry */
3047 NTStatus = 0xC00000B5L; /* I/O Timeout */
3050 else if (code == CM_ERROR_NOACCESS) {
3051 NTStatus = 0xC0000022L; /* Access denied */
3053 else if (code == CM_ERROR_READONLY) {
3054 NTStatus = 0xC00000A2L; /* Write protected */
3056 else if (code == CM_ERROR_NOSUCHFILE ||
3057 code == CM_ERROR_BPLUS_NOMATCH) {
3058 NTStatus = 0xC0000034L; /* Name not found */
3060 else if (code == CM_ERROR_NOSUCHPATH) {
3061 NTStatus = 0xC000003AL; /* Object path not found */
3063 else if (code == CM_ERROR_TOOBIG) {
3064 NTStatus = 0xC000007BL; /* Invalid image format */
3066 else if (code == CM_ERROR_INVAL) {
3067 NTStatus = 0xC000000DL; /* Invalid parameter */
3069 else if (code == CM_ERROR_BADFD) {
3070 NTStatus = 0xC0000008L; /* Invalid handle */
3072 else if (code == CM_ERROR_BADFDOP) {
3073 NTStatus = 0xC0000022L; /* Access denied */
3075 else if (code == CM_ERROR_UNKNOWN) {
3076 NTStatus = 0xC0000022L; /* Access denied */
3078 else if (code == CM_ERROR_EXISTS) {
3079 NTStatus = 0xC0000035L; /* Object name collision */
3081 else if (code == CM_ERROR_NOTEMPTY) {
3082 NTStatus = 0xC0000101L; /* Directory not empty */
3084 else if (code == CM_ERROR_CROSSDEVLINK) {
3085 NTStatus = 0xC00000D4L; /* Not same device */
3087 else if (code == CM_ERROR_NOTDIR) {
3088 NTStatus = 0xC0000103L; /* Not a directory */
3090 else if (code == CM_ERROR_ISDIR) {
3091 NTStatus = 0xC00000BAL; /* File is a directory */
3093 else if (code == CM_ERROR_BADOP) {
3095 /* I have no idea where this comes from */
3096 NTStatus = 0xC09820FFL; /* SMB no support */
3098 NTStatus = 0xC00000BBL; /* Not supported */
3099 #endif /* COMMENT */
3101 else if (code == CM_ERROR_BADSHARENAME) {
3102 NTStatus = 0xC00000BEL; /* Bad network path (server valid, share bad) */
3104 else if (code == CM_ERROR_NOIPC) {
3106 NTStatus = 0xC0000022L; /* Access Denied */
3108 NTStatus = 0xC000013DL; /* Remote Resources */
3111 else if (code == CM_ERROR_CLOCKSKEW ||
3112 code == RXKADNOAUTH) {
3113 NTStatus = 0xC0000133L; /* Time difference at DC */
3115 else if (code == CM_ERROR_BADTID) {
3116 NTStatus = 0xC0982005L; /* SMB bad TID */
3118 else if (code == CM_ERROR_USESTD) {
3119 NTStatus = 0xC09820FBL; /* SMB use standard */
3121 else if (code == CM_ERROR_QUOTA) {
3122 NTStatus = 0xC0000044L; /* Quota exceeded */
3124 else if (code == CM_ERROR_SPACE) {
3125 NTStatus = 0xC000007FL; /* Disk full */
3127 else if (code == CM_ERROR_ATSYS) {
3128 NTStatus = 0xC0000033L; /* Object name invalid */
3130 else if (code == CM_ERROR_BADNTFILENAME) {
3131 NTStatus = 0xC0000033L; /* Object name invalid */
3133 else if (code == CM_ERROR_WOULDBLOCK) {
3134 NTStatus = 0xC00000D8L; /* Can't wait */
3136 else if (code == CM_ERROR_SHARING_VIOLATION) {
3137 NTStatus = 0xC0000043L; /* Sharing violation */
3139 else if (code == CM_ERROR_LOCK_CONFLICT) {
3140 NTStatus = 0xC0000054L; /* Lock conflict */
3142 else if (code == CM_ERROR_PARTIALWRITE) {
3143 NTStatus = 0xC000007FL; /* Disk full */
3145 else if (code == CM_ERROR_BUFFERTOOSMALL) {
3146 NTStatus = 0xC0000023L; /* Buffer too small */
3148 else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
3149 NTStatus = 0xC0000035L; /* Object name collision */
3151 else if (code == CM_ERROR_BADPASSWORD) {
3152 NTStatus = 0xC000006DL; /* unknown username or bad password */
3154 else if (code == CM_ERROR_BADLOGONTYPE) {
3155 NTStatus = 0xC000015BL; /* logon type not granted */
3157 else if (code == CM_ERROR_GSSCONTINUE) {
3158 NTStatus = 0xC0000016L; /* more processing required */
3160 else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
3162 NTStatus = 0xC0000280L; /* reparse point not resolved */
3164 NTStatus = 0xC0000022L; /* Access Denied */
3167 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3168 NTStatus = 0xC0000257L; /* Path Not Covered */
3170 else if (code == CM_ERROR_ALLBUSY) {
3172 NTStatus = 0xC000022DL; /* Retry */
3174 NTStatus = 0xC00000B5L; /* I/O Timeout */
3177 else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
3178 NTStatus = 0xC000003AL; /* Path not found */
3180 else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
3181 NTStatus = 0xC0000322L; /* No Kerberos key */
3183 else if (code == CM_ERROR_BAD_LEVEL) {
3184 NTStatus = 0xC0000148L; /* Invalid Level */
3186 else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
3187 NTStatus = 0xC000007EL; /* Range Not Locked */
3189 else if (code == CM_ERROR_NOSUCHDEVICE) {
3190 NTStatus = 0xC000000EL; /* No Such Device */
3192 else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
3193 NTStatus = 0xC0000055L; /* Lock Not Granted */
3195 else if (code == ENOMEM) {
3196 NTStatus = 0xC0000017L; /* Out of Memory */
3198 else if (code == CM_ERROR_RPC_MOREDATA) {
3199 NTStatus = 0x80000005L; /* Buffer overflow */
3202 NTStatus = 0xC0982001L; /* SMB non-specific error */
3205 *NTStatusp = NTStatus;
3206 osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
3210 * NTSTATUS <-> Win32 Error Translation
3211 * http://support.microsoft.com/kb/113996
3213 void smb_MapWin32Error(long code, unsigned long *Win32Ep)
3215 unsigned long Win32E;
3217 /* map CM_ERROR_* errors to Win32 32-bit error codes */
3221 else if (code == CM_ERROR_NOSUCHCELL) {
3222 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3224 else if (code == CM_ERROR_NOSUCHVOLUME) {
3225 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3227 else if (code == CM_ERROR_TIMEDOUT) {
3229 Win32E = ERROR_SHARING_PAUSED; /* Sharing Paused */
3231 Win32E = ERROR_UNEXP_NET_ERR; /* Timeout */
3234 else if (code == CM_ERROR_RETRY) {
3235 Win32E = ERROR_RETRY; /* Retry */
3237 else if (code == CM_ERROR_NOACCESS) {
3238 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3240 else if (code == CM_ERROR_READONLY) {
3241 Win32E = ERROR_WRITE_PROTECT; /* Write protected */
3243 else if (code == CM_ERROR_NOSUCHFILE ||
3244 code == CM_ERROR_BPLUS_NOMATCH) {
3245 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3247 else if (code == CM_ERROR_NOSUCHPATH) {
3248 Win32E = ERROR_PATH_NOT_FOUND; /* Object path not found */
3250 else if (code == CM_ERROR_TOOBIG) {
3251 Win32E = ERROR_BAD_EXE_FORMAT; /* Invalid image format */
3253 else if (code == CM_ERROR_INVAL) {
3254 Win32E = ERROR_INVALID_PARAMETER;/* Invalid parameter */
3256 else if (code == CM_ERROR_BADFD) {
3257 Win32E = ERROR_INVALID_HANDLE; /* Invalid handle */
3259 else if (code == CM_ERROR_BADFDOP) {
3260 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3262 else if (code == CM_ERROR_UNKNOWN) {
3263 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3265 else if (code == CM_ERROR_EXISTS) {
3266 Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
3268 else if (code == CM_ERROR_NOTEMPTY) {
3269 Win32E = ERROR_DIR_NOT_EMPTY; /* Directory not empty */
3271 else if (code == CM_ERROR_CROSSDEVLINK) {
3272 Win32E = ERROR_NOT_SAME_DEVICE; /* Not same device */
3274 else if (code == CM_ERROR_NOTDIR) {
3275 Win32E = ERROR_DIRECTORY; /* Not a directory */
3277 else if (code == CM_ERROR_ISDIR) {
3278 Win32E = ERROR_ACCESS_DENIED; /* File is a directory */
3280 else if (code == CM_ERROR_BADOP) {
3281 Win32E = ERROR_NOT_SUPPORTED; /* Not supported */
3283 else if (code == CM_ERROR_BADSHARENAME) {
3284 Win32E = ERROR_BAD_NETPATH; /* Bad network path (server valid, share bad) */
3286 else if (code == CM_ERROR_NOIPC) {
3288 Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
3290 Win32E = ERROR_REM_NOT_LIST; /* Remote Resources */
3293 else if (code == CM_ERROR_CLOCKSKEW ||
3294 code == RXKADNOAUTH) {
3295 Win32E = ERROR_TIME_SKEW; /* Time difference at DC */
3297 else if (code == CM_ERROR_BADTID) {
3298 Win32E = ERROR_FILE_NOT_FOUND; /* SMB bad TID */
3300 else if (code == CM_ERROR_USESTD) {
3301 Win32E = ERROR_ACCESS_DENIED; /* SMB use standard */
3303 else if (code == CM_ERROR_QUOTA) {
3304 Win32E = ERROR_NOT_ENOUGH_QUOTA;/* Quota exceeded */
3306 else if (code == CM_ERROR_SPACE) {
3307 Win32E = ERROR_DISK_FULL; /* Disk full */
3309 else if (code == CM_ERROR_ATSYS) {
3310 Win32E = ERROR_INVALID_NAME; /* Object name invalid */
3312 else if (code == CM_ERROR_BADNTFILENAME) {
3313 Win32E = ERROR_INVALID_NAME; /* Object name invalid */
3315 else if (code == CM_ERROR_WOULDBLOCK) {
3316 Win32E = WAIT_TIMEOUT; /* Can't wait */
3318 else if (code == CM_ERROR_SHARING_VIOLATION) {
3319 Win32E = ERROR_SHARING_VIOLATION; /* Sharing violation */
3321 else if (code == CM_ERROR_LOCK_CONFLICT) {
3322 Win32E = ERROR_LOCK_VIOLATION; /* Lock conflict */
3324 else if (code == CM_ERROR_PARTIALWRITE) {
3325 Win32E = ERROR_DISK_FULL; /* Disk full */
3327 else if (code == CM_ERROR_BUFFERTOOSMALL) {
3328 Win32E = ERROR_INSUFFICIENT_BUFFER; /* Buffer too small */
3330 else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
3331 Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
3333 else if (code == CM_ERROR_BADPASSWORD) {
3334 Win32E = ERROR_LOGON_FAILURE; /* unknown username or bad password */
3336 else if (code == CM_ERROR_BADLOGONTYPE) {
3337 Win32E = ERROR_INVALID_LOGON_TYPE; /* logon type not granted */
3339 else if (code == CM_ERROR_GSSCONTINUE) {
3340 Win32E = ERROR_MORE_DATA; /* more processing required */
3342 else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
3344 Win32E = ERROR_CANT_RESOLVE_FILENAME; /* reparse point not resolved */
3346 Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
3349 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3350 Win32E = ERROR_HOST_UNREACHABLE; /* Path Not Covered */
3352 else if (code == CM_ERROR_ALLBUSY) {
3353 Win32E = ERROR_RETRY; /* Retry */
3355 else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
3356 Win32E = ERROR_HOST_UNREACHABLE; /* Path not found */
3358 else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
3359 Win32E = SEC_E_NO_KERB_KEY; /* No Kerberos key */
3361 else if (code == CM_ERROR_BAD_LEVEL) {
3362 Win32E = ERROR_INVALID_LEVEL; /* Invalid Level */
3364 else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
3365 Win32E = ERROR_NOT_LOCKED; /* Range Not Locked */
3367 else if (code == CM_ERROR_NOSUCHDEVICE) {
3368 Win32E = ERROR_FILE_NOT_FOUND; /* No Such Device */
3370 else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
3371 Win32E = ERROR_LOCK_VIOLATION; /* Lock Not Granted */
3373 else if (code == ENOMEM) {
3374 Win32E = ERROR_NOT_ENOUGH_MEMORY; /* Out of Memory */
3376 else if (code == CM_ERROR_RPC_MOREDATA) {
3377 Win32E = ERROR_MORE_DATA; /* Buffer overflow */
3380 Win32E = ERROR_GEN_FAILURE; /* SMB non-specific error */
3384 osi_Log2(smb_logp, "SMB SEND code %lX as Win32 %lX", code, Win32E);
3387 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
3388 unsigned char *classp)
3390 unsigned char class;
3391 unsigned short error;
3393 /* map CM_ERROR_* errors to SMB errors */
3394 if (code == CM_ERROR_NOSUCHCELL) {
3396 error = 3; /* bad path */
3398 else if (code == CM_ERROR_NOSUCHVOLUME) {
3400 error = 3; /* bad path */
3402 else if (code == CM_ERROR_TIMEDOUT) {
3404 error = 81; /* server is paused */
3406 else if (code == CM_ERROR_RETRY) {
3407 class = 2; /* shouldn't happen */
3410 else if (code == CM_ERROR_NOACCESS) {
3412 error = 4; /* bad access */
3414 else if (code == CM_ERROR_READONLY) {
3416 error = 19; /* read only */
3418 else if (code == CM_ERROR_NOSUCHFILE ||
3419 code == CM_ERROR_BPLUS_NOMATCH) {
3421 error = 2; /* ENOENT! */
3423 else if (code == CM_ERROR_NOSUCHPATH) {
3425 error = 3; /* Bad path */
3427 else if (code == CM_ERROR_TOOBIG) {
3429 error = 11; /* bad format */
3431 else if (code == CM_ERROR_INVAL) {
3432 class = 2; /* server non-specific error code */
3435 else if (code == CM_ERROR_BADFD) {
3437 error = 6; /* invalid file handle */
3439 else if (code == CM_ERROR_BADFDOP) {
3440 class = 1; /* invalid op on FD */
3443 else if (code == CM_ERROR_EXISTS) {
3445 error = 80; /* file already exists */
3447 else if (code == CM_ERROR_NOTEMPTY) {
3449 error = 5; /* delete directory not empty */
3451 else if (code == CM_ERROR_CROSSDEVLINK) {
3453 error = 17; /* EXDEV */
3455 else if (code == CM_ERROR_NOTDIR) {
3456 class = 1; /* bad path */
3459 else if (code == CM_ERROR_ISDIR) {
3460 class = 1; /* access denied; DOS doesn't have a good match */
3463 else if (code == CM_ERROR_BADOP) {
3467 else if (code == CM_ERROR_BADSHARENAME) {
3471 else if (code == CM_ERROR_NOIPC) {
3473 error = 4; /* bad access */
3475 else if (code == CM_ERROR_CLOCKSKEW) {
3476 class = 1; /* invalid function */
3479 else if (code == CM_ERROR_BADTID) {
3483 else if (code == CM_ERROR_USESTD) {
3487 else if (code == CM_ERROR_REMOTECONN) {
3491 else if (code == CM_ERROR_QUOTA) {
3492 if (vcp->flags & SMB_VCFLAG_USEV3) {
3494 error = 39; /* disk full */
3498 error = 5; /* access denied */
3501 else if (code == CM_ERROR_SPACE) {
3502 if (vcp->flags & SMB_VCFLAG_USEV3) {
3504 error = 39; /* disk full */
3508 error = 5; /* access denied */
3511 else if (code == CM_ERROR_PARTIALWRITE) {
3513 error = 39; /* disk full */
3515 else if (code == CM_ERROR_ATSYS) {
3517 error = 2; /* ENOENT */
3519 else if (code == CM_ERROR_WOULDBLOCK) {
3521 error = 33; /* lock conflict */
3523 else if (code == CM_ERROR_LOCK_CONFLICT) {
3525 error = 33; /* lock conflict */
3527 else if (code == CM_ERROR_SHARING_VIOLATION) {
3529 error = 33; /* lock conflict */
3531 else if (code == CM_ERROR_NOFILES) {
3533 error = 18; /* no files in search */
3535 else if (code == CM_ERROR_RENAME_IDENTICAL) {
3537 error = 183; /* Samba uses this */
3539 else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
3540 /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
3542 error = 2; /* bad password */
3544 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3546 error = 3; /* bad path */
3555 osi_Log3(smb_logp, "SMB SEND code %lX as SMB %d: %d", code, class, error);
3558 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3560 osi_Log0(smb_logp,"SendCoreBadOp - NOT_SUPPORTED");
3561 return CM_ERROR_BADOP;
3565 long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3567 unsigned short EchoCount, i;
3568 char *data, *outdata;
3571 EchoCount = (unsigned short) smb_GetSMBParm(inp, 0);
3573 for (i=1; i<=EchoCount; i++) {
3574 data = smb_GetSMBData(inp, &dataSize);
3575 smb_SetSMBParm(outp, 0, i);
3576 smb_SetSMBDataLength(outp, dataSize);
3577 outdata = smb_GetSMBData(outp, NULL);
3578 memcpy(outdata, data, dataSize);
3579 smb_SendPacket(vcp, outp);
3585 /* SMB_COM_READ_RAW */
3586 long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3589 long count, minCount, finalCount;
3593 smb_t *smbp = (smb_t*) inp;
3595 cm_user_t *userp = NULL;
3598 char *rawBuf = NULL;
3603 fd = smb_GetSMBParm(inp, 0);
3604 count = smb_GetSMBParm(inp, 3);
3605 minCount = smb_GetSMBParm(inp, 4);
3606 offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
3608 if (*inp->wctp == 10) {
3609 /* we were sent a request with 64-bit file offsets */
3610 #ifdef AFS_LARGEFILES
3611 offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
3613 if (LargeIntegerLessThanZero(offset)) {
3614 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
3618 if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
3619 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset. Dropping request.");
3622 offset.HighPart = 0;
3626 /* we were sent a request with 32-bit file offsets */
3627 offset.HighPart = 0;
3630 osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
3631 fd, offset.HighPart, offset.LowPart, count);
3633 fidp = smb_FindFID(vcp, fd, 0);
3635 osi_Log2(smb_logp, "smb_ReceiveCoreReadRaw Unknown SMB Fid vcp 0x%p fid %d",
3639 lock_ObtainMutex(&fidp->mx);
3641 lock_ReleaseMutex(&fidp->mx);
3642 smb_ReleaseFID(fidp);
3643 return CM_ERROR_BADFD;
3646 if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
3647 lock_ReleaseMutex(&fidp->mx);
3648 smb_CloseFID(vcp, fidp, NULL, 0);
3649 code = CM_ERROR_NOSUCHFILE;
3655 LARGE_INTEGER LOffset, LLength;
3658 key = cm_GenerateKey(vcp->vcID, pid, fd);
3660 LOffset.HighPart = offset.HighPart;
3661 LOffset.LowPart = offset.LowPart;
3662 LLength.HighPart = 0;
3663 LLength.LowPart = count;
3665 lock_ObtainWrite(&fidp->scp->rw);
3666 code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
3667 lock_ReleaseWrite(&fidp->scp->rw);
3670 lock_ReleaseMutex(&fidp->mx);
3674 lock_ObtainMutex(&smb_RawBufLock);
3676 /* Get a raw buf, from head of list */
3677 rawBuf = smb_RawBufs;
3678 smb_RawBufs = *(char **)smb_RawBufs;
3680 lock_ReleaseMutex(&smb_RawBufLock);
3682 lock_ReleaseMutex(&fidp->mx);
3686 if (fidp->flags & SMB_FID_IOCTL)
3688 rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
3690 /* Give back raw buffer */
3691 lock_ObtainMutex(&smb_RawBufLock);
3692 *((char **) rawBuf) = smb_RawBufs;
3694 smb_RawBufs = rawBuf;
3695 lock_ReleaseMutex(&smb_RawBufLock);
3698 lock_ReleaseMutex(&fidp->mx);
3699 smb_ReleaseFID(fidp);
3702 lock_ReleaseMutex(&fidp->mx);
3704 userp = smb_GetUserFromVCP(vcp, inp);
3706 code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
3712 cm_ReleaseUser(userp);
3715 smb_ReleaseFID(fidp);
3719 memset(ncbp, 0, sizeof(NCB));
3721 ncbp->ncb_length = (unsigned short) finalCount;
3722 ncbp->ncb_lsn = (unsigned char) vcp->lsn;