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 /* hide dot files? */
138 int smb_hideDotFiles;
140 /* Negotiate Unicode support? */
143 /* global state about V3 protocols */
144 int smb_useV3; /* try to negotiate V3 */
146 static int showErrors = 0;
147 /* MessageBox or something like it */
148 int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT)
152 * Time in Unix format of midnight, 1/1/1970 local time.
153 * When added to dosUTime, gives Unix (AFS) time.
155 time_t smb_localZero = 0;
157 char *smb_localNamep = NULL;
159 smb_vc_t *smb_allVCsp;
160 smb_vc_t *smb_deadVCsp;
162 smb_username_t *usernamesp = NULL;
164 smb_waitingLockRequest_t *smb_allWaitingLocks;
167 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
168 NCB *ncbp, raw_write_cont_t *rwcp);
169 int smb_NetbiosInit(int);
172 void smb_LogPacket(smb_packet_t *packet);
173 #endif /* LOG_PACKET */
175 clientchar_t smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = _C(""); /* domain name */
176 int smb_ServerDomainNameLength = 0;
177 clientchar_t smb_ServerOS[] = _C("Windows 5.0"); /* Faux OS String */
178 int smb_ServerOSLength = lengthof(smb_ServerOS);
179 clientchar_t smb_ServerLanManager[] = _C("Windows 2000 LAN Manager"); /* Faux LAN Manager string */
180 int smb_ServerLanManagerLength = lengthof(smb_ServerLanManager);
182 /* Faux server GUID. This is never checked. */
183 GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
185 void smb_InitReq(cm_req_t *reqp)
188 reqp->flags |= CM_REQ_SOURCE_SMB;
191 const char * ncb_error_string(int code)
195 case 0x01: s = "NRC_BUFLEN llegal buffer length"; break;
196 case 0x03: s = "NRC_ILLCMD illegal command"; break;
197 case 0x05: s = "NRC_CMDTMO command timed out"; break;
198 case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break;
199 case 0x07: s = "NRC_BADDR illegal buffer address"; break;
200 case 0x08: s = "NRC_SNUMOUT session number out of range"; break;
201 case 0x09: s = "NRC_NORES no resource available"; break;
202 case 0x0a: s = "NRC_SCLOSED asession closed"; break;
203 case 0x0b: s = "NRC_CMDCAN command cancelled"; break;
204 case 0x0d: s = "NRC_DUPNAME duplicate name"; break;
205 case 0x0e: s = "NRC_NAMTFUL name table full"; break;
206 case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break;
207 case 0x11: s = "NRC_LOCTFUL local session table full"; break;
208 case 0x12: s = "NRC_REMTFUL remote session table full"; break;
209 case 0x13: s = "NRC_ILLNN illegal name number"; break;
210 case 0x14: s = "NRC_NOCALL no callname"; break;
211 case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME"; break;
212 case 0x16: s = "NRC_INUSE name in use on remote adapter"; break;
213 case 0x17: s = "NRC_NAMERR name deleted"; break;
214 case 0x18: s = "NRC_SABORT session ended abnormally"; break;
215 case 0x19: s = "NRC_NAMCONF name conflict detected"; break;
216 case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying"; break;
217 case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
218 case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid"; break;
219 case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break;
220 case 0x26: s = "NRC_CANCEL command not valid to cancel"; break;
221 case 0x30: s = "NRC_DUPENV name defined by anther local process"; break;
222 case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required"; break;
223 case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted"; break;
224 case 0x36: s = "NRC_MAXAPPS max number of applications exceeded"; break;
225 case 0x37: s = "NRC_NOSAPS no saps available for netbios"; break;
226 case 0x38: s = "NRC_NORESOURCES requested resources are not available"; break;
227 case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment"; break;
228 case 0x3B: s = "NRC_INVDDID invalid NCB DDID"; break;
229 case 0x3C: s = "NRC_LOCKFAILlock of user area failed"; break;
230 case 0x3f: s = "NRC_OPENERR NETBIOS not loaded"; break;
231 case 0x40: s = "NRC_SYSTEM system error"; break;
232 default: s = "unknown error";
238 char * myCrt_Dispatch(int i)
243 return "(00)ReceiveCoreMakeDir";
245 return "(01)ReceiveCoreRemoveDir";
247 return "(02)ReceiveCoreOpen";
249 return "(03)ReceiveCoreCreate";
251 return "(04)ReceiveCoreClose";
253 return "(05)ReceiveCoreFlush";
255 return "(06)ReceiveCoreUnlink";
257 return "(07)ReceiveCoreRename";
259 return "(08)ReceiveCoreGetFileAttributes";
261 return "(09)ReceiveCoreSetFileAttributes";
263 return "(0a)ReceiveCoreRead";
265 return "(0b)ReceiveCoreWrite";
267 return "(0c)ReceiveCoreLockRecord";
269 return "(0d)ReceiveCoreUnlockRecord";
271 return "(0e)SendCoreBadOp";
273 return "(0f)ReceiveCoreCreate";
275 return "(10)ReceiveCoreCheckPath";
277 return "(11)SendCoreBadOp";
279 return "(12)ReceiveCoreSeek";
281 return "(1a)ReceiveCoreReadRaw";
283 return "(1d)ReceiveCoreWriteRawDummy";
285 return "(22)ReceiveV3SetAttributes";
287 return "(23)ReceiveV3GetAttributes";
289 return "(24)ReceiveV3LockingX";
291 return "(25)ReceiveV3Trans";
293 return "(26)ReceiveV3Trans[aux]";
295 return "(29)SendCoreBadOp";
297 return "(2b)ReceiveCoreEcho";
299 return "(2d)ReceiveV3OpenX";
301 return "(2e)ReceiveV3ReadX";
303 return "(2f)ReceiveV3WriteX";
305 return "(32)ReceiveV3Tran2A";
307 return "(33)ReceiveV3Tran2A[aux]";
309 return "(34)ReceiveV3FindClose";
311 return "(35)ReceiveV3FindNotifyClose";
313 return "(70)ReceiveCoreTreeConnect";
315 return "(71)ReceiveCoreTreeDisconnect";
317 return "(72)ReceiveNegotiate";
319 return "(73)ReceiveV3SessionSetupX";
321 return "(74)ReceiveV3UserLogoffX";
323 return "(75)ReceiveV3TreeConnectX";
325 return "(80)ReceiveCoreGetDiskAttributes";
327 return "(81)ReceiveCoreSearchDir";
331 return "(83)FindUnique";
333 return "(84)FindClose";
335 return "(A0)ReceiveNTTransact";
337 return "(A2)ReceiveNTCreateX";
339 return "(A4)ReceiveNTCancel";
341 return "(A5)ReceiveNTRename";
343 return "(C0)OpenPrintFile";
345 return "(C1)WritePrintFile";
347 return "(C2)ClosePrintFile";
349 return "(C3)GetPrintQueue";
351 return "(D8)ReadBulk";
353 return "(D9)WriteBulk";
355 return "(DA)WriteBulkData";
357 return "unknown SMB op";
361 char * myCrt_2Dispatch(int i)
366 return "unknown SMB op-2";
368 return "S(00)CreateFile_ReceiveTran2Open";
370 return "S(01)FindFirst_ReceiveTran2SearchDir";
372 return "S(02)FindNext_ReceiveTran2SearchDir"; /* FindNext */
374 return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
376 return "S(04)SetFileSystem_ReceiveTran2SetFSInfo";
378 return "S(05)QueryPathInfo_ReceiveTran2QPathInfo";
380 return "S(06)SetPathInfo_ReceiveTran2SetPathInfo";
382 return "S(07)QueryFileInfo_ReceiveTran2QFileInfo";
384 return "S(08)SetFileInfo_ReceiveTran2SetFileInfo";
386 return "S(09)_ReceiveTran2FSCTL";
388 return "S(0a)_ReceiveTran2IOCTL";
390 return "S(0b)_ReceiveTran2FindNotifyFirst";
392 return "S(0c)_ReceiveTran2FindNotifyNext";
394 return "S(0d)_ReceiveTran2CreateDirectory";
396 return "S(0e)_ReceiveTran2SessionSetup";
398 return "S(0f)_QueryFileSystemInformationFid";
400 return "S(10)_ReceiveTran2GetDfsReferral";
402 return "S(11)_ReceiveTran2ReportDfsInconsistency";
406 char * myCrt_RapDispatch(int i)
411 return "unknown RAP OP";
413 return "RAP(0)NetShareEnum";
415 return "RAP(1)NetShareGetInfo";
417 return "RAP(13)NetServerGetInfo";
419 return "RAP(63)NetWkStaGetInfo";
423 char * myCrt_NmpipeDispatch(int i)
426 case SMB_TRANS_SET_NMPIPE_STATE:
427 return "SET NMPIPE STATE";
429 case SMB_TRANS_RAW_READ_NMPIPE:
430 return "RAW READ NMPIPE";
432 case SMB_TRANS_QUERY_NMPIPE_STATE:
433 return "QUERY NMPIPE STATE";
435 case SMB_TRANS_QUERY_NMPIPE_INFO:
436 return "QUERY NMPIPE INFO";
438 case SMB_TRANS_PEEK_NMPIPE:
439 return "PEEK NMPIPE";
441 case SMB_TRANS_TRANSACT_NMPIPE:
442 return "TRANSACT NMPIPE";
444 case SMB_TRANS_RAW_WRITE_NMPIPE:
445 return "WRITE NMPIPE";
447 case SMB_TRANS_READ_NMPIPE:
448 return "READ NMPIPE";
450 case SMB_TRANS_WRITE_NMPIPE:
451 return "WRITE NMPIPE";
453 case SMB_TRANS_WAIT_NMPIPE:
454 return "WAIT NMPIPE";
456 case SMB_TRANS_CALL_NMPIPE:
457 return "CALL NMPIPE";
462 /* scache must be locked */
463 unsigned int smb_Attributes(cm_scache_t *scp)
467 if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
468 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
469 scp->fileType == CM_SCACHETYPE_INVALID)
471 attrs = SMB_ATTR_DIRECTORY;
472 #ifdef SPECIAL_FOLDERS
473 attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
474 #endif /* SPECIAL_FOLDERS */
475 } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
476 attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
481 * We used to mark a file RO if it was in an RO volume, but that
482 * turns out to be impolitic in NT. See defect 10007.
485 if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
486 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
488 if ((scp->unixModeBits & 0222) == 0)
489 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
495 /* Check if the named file/dir is a dotfile/dotdir */
496 /* String pointed to by lastComp can have leading slashes, but otherwise should have
497 no other patch components */
498 unsigned int smb_IsDotFile(clientchar_t *lastComp) {
502 /* skip over slashes */
503 for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
508 /* nulls, curdir and parent dir doesn't count */
514 if(*(s+1) == _C('.') && !*(s + 2))
521 static int ExtractBits(WORD bits, short start, short len)
528 num = bits << (16 - end);
529 num = num >> ((16 - end) + start);
534 void ShowUnixTime(char *FuncName, time_t unixTime)
539 cm_LargeSearchTimeFromUnixTime(&ft, unixTime);
541 if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
542 osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
544 int day, month, year, sec, min, hour;
547 day = ExtractBits(wDate, 0, 5);
548 month = ExtractBits(wDate, 5, 4);
549 year = ExtractBits(wDate, 9, 7) + 1980;
551 sec = ExtractBits(wTime, 0, 5);
552 min = ExtractBits(wTime, 5, 6);
553 hour = ExtractBits(wTime, 11, 5);
555 sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
556 osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
560 /* Determine if we are observing daylight savings time */
561 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
563 TIME_ZONE_INFORMATION timeZoneInformation;
564 SYSTEMTIME utc, local, localDST;
566 /* Get the time zone info. NT uses this to calc if we are in DST. */
567 GetTimeZoneInformation(&timeZoneInformation);
569 /* Return the daylight bias */
570 *pDstBias = timeZoneInformation.DaylightBias;
572 /* Return the bias */
573 *pBias = timeZoneInformation.Bias;
575 /* Now determine if DST is being observed */
577 /* Get the UTC (GMT) time */
580 /* Convert UTC time to local time using the time zone info. If we are
581 observing DST, the calculated local time will include this.
583 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &localDST);
585 /* Set the daylight bias to 0. The daylight bias is the amount of change
586 * in time that we use for daylight savings time. By setting this to 0
587 * we cause there to be no change in time during daylight savings time.
589 timeZoneInformation.DaylightBias = 0;
591 /* Convert the utc time to local time again, but this time without any
592 adjustment for daylight savings time.
594 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &local);
596 /* If the two times are different, then it means that the localDST that
597 we calculated includes the daylight bias, and therefore we are
598 observing daylight savings time.
600 *pDST = localDST.wHour != local.wHour;
604 void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
606 BOOL dst; /* Will be TRUE if observing DST */
607 LONG dstBias; /* Offset from local time if observing DST */
608 LONG bias; /* Offset from GMT for local time */
611 * This function will adjust the last write time to compensate
612 * for two bugs in the smb client:
614 * 1) During Daylight Savings Time, the LastWriteTime is ahead
615 * in time by the DaylightBias (ignoring the sign - the
616 * DaylightBias is always stored as a negative number). If
617 * the DaylightBias is -60, then the LastWriteTime will be
618 * ahead by 60 minutes.
620 * 2) If the local time zone is a positive offset from GMT, then
621 * the LastWriteTime will be the correct local time plus the
622 * Bias (ignoring the sign - a positive offset from GMT is
623 * always stored as a negative Bias). If the Bias is -120,
624 * then the LastWriteTime will be ahead by 120 minutes.
626 * These bugs can occur at the same time.
629 GetTimeZoneInfo(&dst, &dstBias, &bias);
631 /* First adjust for DST */
633 *pLastWriteTime -= (-dstBias * 60); /* Convert dstBias to seconds */
635 /* Now adjust for a positive offset from GMT (a negative bias). */
637 *pLastWriteTime -= (-bias * 60); /* Convert bias to seconds */
640 void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
642 time_t diff_t = unixTime - smb_localZero;
643 #if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
644 osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
646 *dosUTimep = (afs_uint32)diff_t;
649 void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
651 *unixTimep = dosTime + smb_localZero;
654 void smb_MarkAllVCsDead(smb_vc_t * exclude)
657 smb_vc_t **vcp_to_cleanup = NULL;
658 int n_to_cleanup = 0;
661 osi_Log1(smb_logp, "Marking all VCs as dead excluding %p", exclude);
663 lock_ObtainWrite(&smb_globalLock); /* for dead_sessions[] */
664 lock_ObtainWrite(&smb_rctLock);
665 for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
667 if (vcp->magic != SMB_VC_MAGIC)
668 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
674 lock_ObtainMutex(&vcp->mx);
675 if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
676 vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
677 lock_ReleaseMutex(&vcp->mx);
678 dead_sessions[vcp->session] = TRUE;
680 lock_ReleaseMutex(&vcp->mx);
685 vcp_to_cleanup = malloc(sizeof(vcp_to_cleanup[0]) * n_to_cleanup);
687 for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
691 vcp_to_cleanup[i++] = vcp;
692 smb_HoldVCNoLock(vcp);
695 osi_assert(i == n_to_cleanup);
697 lock_ReleaseWrite(&smb_rctLock);
698 lock_ReleaseWrite(&smb_globalLock);
700 for (i=0; i < n_to_cleanup; i++) {
701 smb_CleanupDeadVC(vcp_to_cleanup[i]);
702 smb_ReleaseVC(vcp_to_cleanup[i]);
703 vcp_to_cleanup[i] = 0;
706 free(vcp_to_cleanup);
709 #ifdef DEBUG_SMB_REFCOUNT
710 smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line)
712 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
717 lock_ObtainWrite(&smb_globalLock); /* for numVCs */
718 lock_ObtainWrite(&smb_rctLock);
719 for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
720 if (vcp->magic != SMB_VC_MAGIC)
721 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
724 lock_ObtainMutex(&vcp->mx);
725 if (lsn == vcp->lsn && lana == vcp->lana &&
726 !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
727 lock_ReleaseMutex(&vcp->mx);
728 smb_HoldVCNoLock(vcp);
731 lock_ReleaseMutex(&vcp->mx);
733 if (!vcp && (flags & SMB_FLAG_CREATE)) {
734 vcp = malloc(sizeof(*vcp));
735 memset(vcp, 0, sizeof(*vcp));
736 vcp->vcID = ++numVCs;
737 vcp->magic = SMB_VC_MAGIC;
738 vcp->refCount = 2; /* smb_allVCsp and caller */
741 vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
742 vcp->nextp = smb_allVCsp;
744 lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
749 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
750 /* We must obtain a challenge for extended auth
751 * in case the client negotiates smb v3
753 NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
754 MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
755 PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp = NULL;
756 ULONG lsaRespSize = 0;
758 lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
760 nts = LsaCallAuthenticationPackage( smb_lsaHandle,
767 if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS) {
768 osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
769 nts, ntsEx, sizeof(lsaReq), lsaRespSize);
770 afsi_log("MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize %u",
771 nts, ntsEx, lsaRespSize);
773 osi_assertx(nts == STATUS_SUCCESS, "LsaCallAuthenticationPackage failed"); /* this had better work! */
775 if (ntsEx == STATUS_SUCCESS) {
776 memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
779 * This will cause the subsequent authentication to fail but
780 * that is better than us dereferencing a NULL pointer and
783 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
786 LsaFreeReturnBuffer(lsaResp);
789 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
791 if (numVCs >= CM_SESSION_RESERVED) {
793 osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
796 #ifdef DEBUG_SMB_REFCOUNT
798 afsi_log("%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
799 osi_Log4(smb_logp,"%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
802 lock_ReleaseWrite(&smb_rctLock);
803 lock_ReleaseWrite(&smb_globalLock);
807 static int smb_Is8Dot3StarMask(clientchar_t *maskp)
812 for(i=0; i<11; i++) {
814 if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
820 static int smb_IsStarMask(clientchar_t *maskp)
826 if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
832 #ifdef DEBUG_SMB_REFCOUNT
833 void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
834 #define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
836 void smb_ReleaseVCInternal(smb_vc_t *vcp)
842 lock_AssertWrite(&smb_rctLock);
845 if (vcp->refCount == 0) {
846 if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
847 #ifdef DEBUG_SMB_REFCOUNT
848 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
849 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
851 /* remove VCP from smb_deadVCsp */
852 for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
858 lock_FinalizeMutex(&vcp->mx);
859 memset(vcp,0,sizeof(smb_vc_t));
862 #ifdef DEBUG_SMB_REFCOUNT
863 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is alive ref %d", file, line, vcp, vcp->refCount);
865 for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
869 osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
870 avcp?"":"not ",vcp, vcp->refCount);
872 /* This is a wrong. However, I suspect that there is an undercount
873 * and I don't want to release 1.4.1 in a state that will allow
874 * smb_vc_t objects to be deallocated while still in the
875 * smb_allVCsp list. The list is supposed to keep a reference
876 * to the smb_vc_t. Put it back.
880 #ifdef DEBUG_SMB_REFCOUNT
881 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
882 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
886 } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
887 /* The reference count is non-zero but the VC is dead.
888 * This implies that some FIDs, TIDs, etc on the VC have yet to
889 * be cleaned up. If we were not called by smb_CleanupDeadVC(),
890 * add a reference that will be dropped by
891 * smb_CleanupDeadVC() and try to cleanup the VC again.
892 * Eventually the refCount will drop to zero when all of the
893 * active threads working with the VC end their task.
895 if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) {
896 vcp->refCount++; /* put the refCount back */
897 lock_ReleaseWrite(&smb_rctLock);
898 smb_CleanupDeadVC(vcp);
899 #ifdef DEBUG_SMB_REFCOUNT
900 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
901 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
903 lock_ObtainWrite(&smb_rctLock);
906 #ifdef DEBUG_SMB_REFCOUNT
907 afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
908 osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
913 #ifdef DEBUG_SMB_REFCOUNT
914 void smb_ReleaseVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
916 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
919 lock_AssertWrite(&smb_rctLock);
920 osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
921 smb_ReleaseVCInternal(vcp);
924 #ifdef DEBUG_SMB_REFCOUNT
925 void smb_ReleaseVCDbg(smb_vc_t *vcp, char * file, long line)
927 void smb_ReleaseVC(smb_vc_t *vcp)
930 lock_ObtainWrite(&smb_rctLock);
931 osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
932 smb_ReleaseVCInternal(vcp);
933 lock_ReleaseWrite(&smb_rctLock);
936 #ifdef DEBUG_SMB_REFCOUNT
937 void smb_HoldVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
939 void smb_HoldVCNoLock(smb_vc_t *vcp)
942 lock_AssertWrite(&smb_rctLock);
944 #ifdef DEBUG_SMB_REFCOUNT
945 afsi_log("%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
946 osi_Log4(smb_logp,"%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
948 osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
952 #ifdef DEBUG_SMB_REFCOUNT
953 void smb_HoldVCDbg(smb_vc_t *vcp, char * file, long line)
955 void smb_HoldVC(smb_vc_t *vcp)
958 lock_ObtainWrite(&smb_rctLock);
960 #ifdef DEBUG_SMB_REFCOUNT
961 afsi_log("%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
962 osi_Log4(smb_logp,"%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
964 osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
966 lock_ReleaseWrite(&smb_rctLock);
969 void smb_CleanupDeadVC(smb_vc_t *vcp)
977 smb_user_t *uidpIter;
978 smb_user_t *uidpNext;
980 afs_uint32 refCount = 0;
982 lock_ObtainMutex(&vcp->mx);
983 if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
984 lock_ReleaseMutex(&vcp->mx);
985 osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
988 vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
989 lock_ReleaseMutex(&vcp->mx);
990 osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
992 lock_ObtainWrite(&smb_rctLock);
993 /* remove VCP from smb_allVCsp */
994 for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
995 if ((*vcpp)->magic != SMB_VC_MAGIC)
996 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
1000 vcp->nextp = smb_deadVCsp;
1002 /* Hold onto the reference until we are done with this function */
1007 for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
1008 fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
1010 if (fidpIter->deleteOk)
1013 fid = fidpIter->fid;
1014 osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
1016 smb_HoldFIDNoLock(fidpIter);
1017 lock_ReleaseWrite(&smb_rctLock);
1019 smb_CloseFID(vcp, fidpIter, NULL, 0);
1020 smb_ReleaseFID(fidpIter);
1022 lock_ObtainWrite(&smb_rctLock);
1023 fidpNext = vcp->fidsp;
1026 for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
1027 tidpNext = tidpIter->nextp;
1028 if (tidpIter->deleteOk)
1030 tidpIter->deleteOk = 1;
1032 tid = tidpIter->tid;
1033 osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
1035 smb_HoldTIDNoLock(tidpIter);
1036 smb_ReleaseTID(tidpIter, TRUE);
1037 tidpNext = vcp->tidsp;
1040 for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
1041 uidpNext = uidpIter->nextp;
1042 if (uidpIter->deleteOk)
1044 uidpIter->deleteOk = 1;
1046 /* do not add an additional reference count for the smb_user_t
1047 * as the smb_vc_t already is holding a reference */
1048 lock_ReleaseWrite(&smb_rctLock);
1050 smb_ReleaseUID(uidpIter);
1052 lock_ObtainWrite(&smb_rctLock);
1053 uidpNext = vcp->usersp;
1056 /* The vcp is now on the deadVCsp list. We intentionally drop the
1057 * reference so that the refcount can reach 0 and we can delete it
1059 * If the refCount == 1 going into the ReleaseVCNoLock call
1060 * the object will be freed and it won't be safe to clear
1063 refCount = vcp->refCount;
1064 smb_ReleaseVCNoLock(vcp);
1066 lock_ObtainMutex(&vcp->mx);
1067 vcp->flags &= ~SMB_VCFLAG_CLEAN_IN_PROGRESS;
1068 lock_ReleaseMutex(&vcp->mx);
1071 lock_ReleaseWrite(&smb_rctLock);
1072 osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
1075 #ifdef DEBUG_SMB_REFCOUNT
1076 smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char * file, long line)
1078 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
1083 lock_ObtainWrite(&smb_rctLock);
1085 for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
1086 if (tidp->refCount == 0 && tidp->deleteOk) {
1088 smb_ReleaseTID(tidp, TRUE);
1092 if (tid == tidp->tid) {
1097 if (!tidp && (flags & SMB_FLAG_CREATE)) {
1098 tidp = malloc(sizeof(*tidp));
1099 memset(tidp, 0, sizeof(*tidp));
1100 tidp->nextp = vcp->tidsp;
1103 smb_HoldVCNoLock(vcp);
1105 lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
1108 #ifdef DEBUG_SMB_REFCOUNT
1110 afsi_log("%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1111 osi_Log4(smb_logp,"%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1114 lock_ReleaseWrite(&smb_rctLock);
1118 #ifdef DEBUG_SMB_REFCOUNT
1119 void smb_HoldTIDNoLockDbg(smb_tid_t *tidp, char * file, long line)
1121 void smb_HoldTIDNoLock(smb_tid_t *tidp)
1124 lock_AssertWrite(&smb_rctLock);
1126 #ifdef DEBUG_SMB_REFCOUNT
1127 afsi_log("%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1128 osi_Log4(smb_logp,"%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
1132 #ifdef DEBUG_SMB_REFCOUNT
1133 void smb_ReleaseTIDDbg(smb_tid_t *tidp, afs_uint32 locked, char *file, long line)
1135 void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
1140 cm_user_t *userp = NULL;
1141 smb_vc_t *vcp = NULL;
1144 lock_ObtainWrite(&smb_rctLock);
1146 lock_AssertWrite(&smb_rctLock);
1148 osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
1149 #ifdef DEBUG_SMB_REFCOUNT
1150 afsi_log("%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
1151 osi_Log5(smb_logp,"%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
1153 if (tidp->refCount == 0) {
1154 if (tidp->deleteOk) {
1155 ltpp = &tidp->vcp->tidsp;
1156 for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
1160 osi_assertx(tp != NULL, "null smb_tid_t");
1162 lock_FinalizeMutex(&tidp->mx);
1163 userp = tidp->userp; /* remember to drop ref later */
1171 smb_ReleaseVCNoLock(vcp);
1173 lock_ReleaseWrite(&smb_rctLock);
1175 cm_ReleaseUser(userp);
1178 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
1180 smb_user_t *uidp = NULL;
1182 lock_ObtainWrite(&smb_rctLock);
1183 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1184 if (uid == uidp->userID) {
1186 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%S]",
1188 ((uidp->unp)? osi_LogSaveClientString(smb_logp, uidp->unp->name):_C("")));
1192 if (!uidp && (flags & SMB_FLAG_CREATE)) {
1193 uidp = malloc(sizeof(*uidp));
1194 memset(uidp, 0, sizeof(*uidp));
1195 uidp->nextp = vcp->usersp;
1196 uidp->refCount = 2; /* one for the vcp and one for the caller */
1198 smb_HoldVCNoLock(vcp);
1200 lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
1202 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
1204 ((uidp->unp)?osi_LogSaveClientString(smb_logp,uidp->unp->name):_C("")));
1206 lock_ReleaseWrite(&smb_rctLock);
1210 smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
1213 smb_username_t *unp= NULL;
1215 lock_ObtainWrite(&smb_rctLock);
1216 for(unp = usernamesp; unp; unp = unp->nextp) {
1217 if (cm_ClientStrCmpI(unp->name, usern) == 0 &&
1218 cm_ClientStrCmpI(unp->machine, machine) == 0) {
1223 if (!unp && (flags & SMB_FLAG_CREATE)) {
1224 unp = malloc(sizeof(*unp));
1225 memset(unp, 0, sizeof(*unp));
1227 unp->nextp = usernamesp;
1228 unp->name = cm_ClientStrDup(usern);
1229 unp->machine = cm_ClientStrDup(machine);
1231 lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
1232 if (flags & SMB_FLAG_AFSLOGON)
1233 unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
1236 lock_ReleaseWrite(&smb_rctLock);
1240 smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, clientchar_t *usern)
1242 smb_user_t *uidp= NULL;
1244 lock_ObtainWrite(&smb_rctLock);
1245 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1248 if (cm_stricmp_utf16(uidp->unp->name, usern) == 0) {
1250 osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%S]",
1251 vcp,uidp->userID,osi_LogSaveClientString(smb_logp,usern));
1256 lock_ReleaseWrite(&smb_rctLock);
1260 void smb_ReleaseUsername(smb_username_t *unp)
1263 smb_username_t **lupp;
1264 cm_user_t *userp = NULL;
1265 time_t now = osi_Time();
1267 lock_ObtainWrite(&smb_rctLock);
1268 osi_assertx(unp->refCount-- > 0, "smb_username_t refCount 0");
1269 if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
1270 (unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
1272 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1276 osi_assertx(up != NULL, "null smb_username_t");
1278 up->nextp = NULL; /* do not remove this */
1279 lock_FinalizeMutex(&unp->mx);
1285 lock_ReleaseWrite(&smb_rctLock);
1287 cm_ReleaseUser(userp);
1290 void smb_HoldUIDNoLock(smb_user_t *uidp)
1292 lock_AssertWrite(&smb_rctLock);
1296 void smb_ReleaseUID(smb_user_t *uidp)
1300 smb_username_t *unp = NULL;
1302 lock_ObtainWrite(&smb_rctLock);
1303 osi_assertx(uidp->refCount-- > 0, "smb_user_t refCount 0");
1304 if (uidp->refCount == 0) {
1305 lupp = &uidp->vcp->usersp;
1306 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1310 osi_assertx(up != NULL, "null smb_user_t");
1312 lock_FinalizeMutex(&uidp->mx);
1314 smb_ReleaseVCNoLock(uidp->vcp);
1318 lock_ReleaseWrite(&smb_rctLock);
1322 cm_ReleaseUserVCRef(unp->userp);
1323 smb_ReleaseUsername(unp);
1327 cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
1329 cm_user_t *up = NULL;
1334 lock_ObtainMutex(&uidp->mx);
1336 up = uidp->unp->userp;
1339 lock_ReleaseMutex(&uidp->mx);
1345 /* retrieve a held reference to a user structure corresponding to an incoming
1347 * corresponding release function is cm_ReleaseUser.
1349 cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
1352 cm_user_t *up = NULL;
1355 smbp = (smb_t *) inp;
1356 uidp = smb_FindUID(vcp, smbp->uid, 0);
1360 up = smb_GetUserFromUID(uidp);
1362 smb_ReleaseUID(uidp);
1367 * Return a pointer to a pathname extracted from a TID structure. The
1368 * TID structure is not held; assume it won't go away.
1370 long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, clientchar_t ** treepath)
1375 tidp = smb_FindTID(vcp, tid, 0);
1379 if (tidp->flags & SMB_TIDFLAG_IPC) {
1380 code = CM_ERROR_TIDIPC;
1381 /* tidp->pathname would be NULL, but that's fine */
1383 *treepath = tidp->pathname;
1384 smb_ReleaseTID(tidp, FALSE);
1389 /* check to see if we have a chained fid, that is, a fid that comes from an
1390 * OpenAndX message that ran earlier in this packet. In this case, the fid
1391 * field in a read, for example, request, isn't set, since the value is
1392 * supposed to be inherited from the openAndX call.
1394 int smb_ChainFID(int fid, smb_packet_t *inp)
1396 if (inp->fid == 0 || inp->inCount == 0)
1402 /* are we a priv'd user? What does this mean on NT? */
1403 int smb_SUser(cm_user_t *userp)
1408 /* find a file ID. If we pass in 0 we select an unused File ID.
1409 * If the SMB_FLAG_CREATE flag is set, we allocate a new
1410 * smb_fid_t data structure if desired File ID cannot be found.
1412 #ifdef DEBUG_SMB_REFCOUNT
1413 smb_fid_t *smb_FindFIDDbg(smb_vc_t *vcp, unsigned short fid, int flags, char *file, long line)
1415 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
1422 if (!(flags & SMB_FLAG_CREATE))
1427 lock_ObtainWrite(&smb_rctLock);
1429 fid = vcp->fidCounter;
1432 for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
1433 if (fidp->refCount == 0 && fidp->deleteOk) {
1435 lock_ReleaseWrite(&smb_rctLock);
1436 smb_ReleaseFID(fidp);
1437 lock_ObtainWrite(&smb_rctLock);
1439 * We dropped the smb_rctLock so the fid value we are using
1440 * may now be used by another thread. Start over with the
1441 * current vcp->fidCounter.
1444 fid = vcp->fidCounter;
1447 if (fid == fidp->fid) {
1449 osi_Log1(smb_logp, "smb_FindFID New Fid Requested. fid %d found -- retrying ...", fid);
1451 if (fid == 0xFFFF) {
1453 "New FID number wraps on vcp 0x%x", vcp);
1463 if (!fidp && (flags & SMB_FLAG_CREATE)) {
1464 char eventName[MAX_PATH];
1468 osi_Log1(smb_logp, "smb_FindFID New Fid Not Requested, Fid %d Not Found and CREATE flag set.", fid);
1470 osi_Log1(smb_logp, "smb_FindFID New Fid Requested. Creating fid %d", fid);
1472 sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
1473 event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
1474 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
1475 osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
1476 thrd_CloseHandle(event);
1478 if (fid == 0xFFFF) {
1479 osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
1485 fidp = malloc(sizeof(*fidp));
1486 memset(fidp, 0, sizeof(*fidp));
1487 osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
1490 smb_HoldVCNoLock(vcp);
1491 lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
1493 fidp->curr_chunk = fidp->prev_chunk = -2;
1494 fidp->raw_write_event = event;
1496 vcp->fidCounter = fid+1;
1497 if (vcp->fidCounter == 0xFFFF) {
1498 osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
1500 vcp->fidCounter = 1;
1505 #ifdef DEBUG_SMB_REFCOUNT
1507 afsi_log("%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1508 osi_Log4(smb_logp,"%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1511 lock_ReleaseWrite(&smb_rctLock);
1516 /* Must not be called with scp->rw held because smb_ReleaseFID might be called */
1517 #ifdef DEBUG_SMB_REFCOUNT
1518 smb_fid_t *smb_FindFIDByScacheDbg(smb_vc_t *vcp, cm_scache_t * scp, char *file, long line)
1520 smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
1523 smb_fid_t *fidp = NULL, *nextp = NULL;
1529 * If the fidp->scp changes out from under us then
1530 * we must not grab a refCount. It means the *fidp
1531 * was processed by smb_CloseFID() and the *fidp is
1532 * no longer valid for use.
1534 lock_ObtainWrite(&smb_rctLock);
1535 for(fidp = vcp->fidsp, (fidp ? fidp->refCount++ : 0); fidp; fidp = nextp, nextp = NULL) {
1536 nextp = (smb_fid_t *) osi_QNext(&fidp->q);
1540 if (scp == fidp->scp) {
1541 lock_ReleaseWrite(&smb_rctLock);
1542 lock_ObtainMutex(&fidp->mx);
1543 lock_ObtainWrite(&smb_rctLock);
1544 if (scp == fidp->scp) {
1545 lock_ReleaseMutex(&fidp->mx);
1548 lock_ReleaseMutex(&fidp->mx);
1551 if (fidp->refCount > 1) {
1554 lock_ReleaseWrite(&smb_rctLock);
1555 smb_ReleaseFID(fidp);
1556 lock_ObtainWrite(&smb_rctLock);
1561 if (nextp->refCount > 1) {
1564 lock_ReleaseWrite(&smb_rctLock);
1565 smb_ReleaseFID(nextp);
1566 lock_ObtainWrite(&smb_rctLock);
1570 #ifdef DEBUG_SMB_REFCOUNT
1572 afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1573 osi_Log4(smb_logp,"%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1576 lock_ReleaseWrite(&smb_rctLock);
1580 #ifdef DEBUG_SMB_REFCOUNT
1581 void smb_HoldFIDNoLockDbg(smb_fid_t *fidp, char *file, long line)
1583 void smb_HoldFIDNoLock(smb_fid_t *fidp)
1586 lock_AssertWrite(&smb_rctLock);
1588 #ifdef DEBUG_SMB_REFCOUNT
1589 afsi_log("%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1590 osi_Log4(smb_logp,"%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
1595 /* smb_ReleaseFID cannot be called while a cm_scache_t rwlock is held */
1596 /* the smb_fid_t->mx and smb_rctLock must not be held */
1597 #ifdef DEBUG_SMB_REFCOUNT
1598 void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
1600 void smb_ReleaseFID(smb_fid_t *fidp)
1603 cm_scache_t *scp = NULL;
1604 cm_user_t *userp = NULL;
1605 smb_vc_t *vcp = NULL;
1606 smb_ioctl_t *ioctlp;
1608 lock_ObtainMutex(&fidp->mx);
1609 lock_ObtainWrite(&smb_rctLock);
1610 osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
1611 #ifdef DEBUG_SMB_REFCOUNT
1612 afsi_log("%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
1613 osi_Log5(smb_logp,"%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
1615 if (fidp->refCount == 0) {
1616 if (fidp->deleteOk) {
1619 scp = fidp->scp; /* release after lock is released */
1621 lock_ObtainWrite(&scp->rw);
1622 scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
1623 lock_ReleaseWrite(&scp->rw);
1624 osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
1627 userp = fidp->userp;
1631 osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
1632 thrd_CloseHandle(fidp->raw_write_event);
1634 /* and see if there is ioctl stuff to free */
1635 ioctlp = fidp->ioctlp;
1638 cm_FreeSpace(ioctlp->prefix);
1639 if (ioctlp->ioctl.inAllocp)
1640 free(ioctlp->ioctl.inAllocp);
1641 if (ioctlp->ioctl.outAllocp)
1642 free(ioctlp->ioctl.outAllocp);
1646 smb_CleanupRPCFid(fidp);
1648 lock_ReleaseMutex(&fidp->mx);
1649 lock_FinalizeMutex(&fidp->mx);
1654 smb_ReleaseVCNoLock(vcp);
1658 lock_ReleaseMutex(&fidp->mx);
1660 lock_ReleaseWrite(&smb_rctLock);
1662 /* now release the scache structure */
1664 cm_ReleaseSCache(scp);
1667 cm_ReleaseUser(userp);
1671 * Case-insensitive search for one string in another;
1672 * used to find variable names in submount pathnames.
1674 static clientchar_t *smb_stristr(clientchar_t *str1, clientchar_t *str2)
1676 clientchar_t *cursor;
1678 for (cursor = str1; *cursor; cursor++)
1679 if (cm_ClientStrCmpI(cursor, str2) == 0)
1686 * Substitute a variable value for its name in a submount pathname. Variable
1687 * name has been identified by smb_stristr() and is in substr. Variable name
1688 * length (plus one) is in substr_size. Variable value is in newstr.
1690 static void smb_subst(clientchar_t *str1, int cchstr1, clientchar_t *substr,
1691 unsigned int substr_size, clientchar_t *newstr)
1693 clientchar_t temp[1024];
1695 cm_ClientStrCpy(temp, lengthof(temp), substr + substr_size - 1);
1696 cm_ClientStrCpy(substr, cchstr1 - (substr - str1), newstr);
1697 cm_ClientStrCat(str1, cchstr1, temp);
1700 clientchar_t VNUserName[] = _C("%USERNAME%");
1701 clientchar_t VNLCUserName[] = _C("%LCUSERNAME%");
1702 clientchar_t VNComputerName[] = _C("%COMPUTERNAME%");
1703 clientchar_t VNLCComputerName[] = _C("%LCCOMPUTERNAME%");
1705 typedef struct smb_findShare_rock {
1706 clientchar_t * shareName;
1707 clientchar_t * match;
1709 } smb_findShare_rock_t;
1711 #define SMB_FINDSHARE_EXACT_MATCH 1
1712 #define SMB_FINDSHARE_PARTIAL_MATCH 2
1714 long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
1718 smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
1719 normchar_t normName[MAX_PATH];
1721 if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0])) == 0) {
1722 osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
1723 osi_LogSaveString(smb_logp, dep->name));
1727 if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
1728 if(!cm_ClientStrCmpI(normName, vrock->shareName))
1729 matchType = SMB_FINDSHARE_EXACT_MATCH;
1731 matchType = SMB_FINDSHARE_PARTIAL_MATCH;
1734 vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
1735 vrock->matchType = matchType;
1737 if(matchType == SMB_FINDSHARE_EXACT_MATCH)
1738 return CM_ERROR_STOPNOW;
1744 /* find a shareName in the table of submounts */
1745 int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
1746 clientchar_t *shareName,
1747 clientchar_t **pathNamep)
1751 clientchar_t pathName[1024];
1754 clientchar_t *p, *q;
1755 fschar_t *cellname = NULL;
1758 DWORD allSubmount = 1;
1760 /* if allSubmounts == 0, only return the //mountRoot/all share
1761 * if in fact it has been been created in the subMounts table.
1762 * This is to allow sites that want to restrict access to the
1765 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1766 0, KEY_QUERY_VALUE, &parmKey);
1767 if (code == ERROR_SUCCESS) {
1768 cblen = sizeof(allSubmount);
1769 code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
1770 (BYTE *) &allSubmount, &cblen);
1771 if (code != ERROR_SUCCESS) {
1774 RegCloseKey (parmKey);
1777 if (allSubmount && cm_ClientStrCmpI(shareName, _C("all")) == 0) {
1782 /* In case, the all share is disabled we need to still be able
1783 * to handle ioctl requests
1785 if (cm_ClientStrCmpI(shareName, _C("ioctl$")) == 0) {
1786 *pathNamep = cm_ClientStrDup(_C("/.__ioctl__"));
1790 if (MSRPC_IsWellKnownService(shareName) ||
1791 cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
1792 cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
1798 /* Check for volume references
1800 * They look like <cell>{%,#}<volume>
1802 if (cm_ClientStrChr(shareName, '%') != NULL ||
1803 cm_ClientStrChr(shareName, '#') != NULL) {
1804 clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
1805 /* make room for '/@vol:' + mountchar + NULL terminator*/
1807 osi_Log1(smb_logp, "smb_FindShare found volume reference [%S]",
1808 osi_LogSaveClientString(smb_logp, shareName));
1810 cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
1811 _C("/") _C(CM_PREFIX_VOL) _C("%s"), shareName);
1812 cchlen = (DWORD)(cm_ClientStrLen(pathstr) + 1);
1814 *pathNamep = malloc(cchlen * sizeof(clientchar_t));
1816 cm_ClientStrCpy(*pathNamep, cchlen, pathstr);
1817 cm_ClientStrLwr(*pathNamep);
1818 osi_Log1(smb_logp, " returning pathname [%S]",
1819 osi_LogSaveClientString(smb_logp, *pathNamep));
1827 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
1828 0, KEY_QUERY_VALUE, &parmKey);
1829 if (code == ERROR_SUCCESS) {
1830 cblen = sizeof(pathName);
1831 code = RegQueryValueExW(parmKey, shareName, NULL, NULL,
1832 (BYTE *) pathName, &cblen);
1833 if (code != ERROR_SUCCESS)
1835 RegCloseKey (parmKey);
1839 cchlen = cblen / sizeof(clientchar_t);
1840 if (cchlen != 0 && cchlen != lengthof(pathName) - 1) {
1841 /* We can accept either unix or PC style AFS pathnames. Convert
1842 * Unix-style to PC style here for internal use.
1845 cchlen = lengthof(pathName);
1847 /* within this code block, we maintain, cchlen = writeable
1848 buffer length of p */
1850 if (cm_ClientStrCmpN(p, cm_mountRootC, cm_mountRootCLen) == 0) {
1851 p += cm_mountRootCLen; /* skip mount path */
1852 cchlen -= (DWORD)(p - pathName);
1857 if (*q == _C('/')) *q = _C('\\'); /* change to \ */
1863 clientchar_t temp[1024];
1865 if (var = smb_stristr(p, VNUserName)) {
1866 if (uidp && uidp->unp)
1867 smb_subst(p, cchlen, var, lengthof(VNUserName),uidp->unp->name);
1869 smb_subst(p, cchlen, var, lengthof(VNUserName), _C(" "));
1871 else if (var = smb_stristr(p, VNLCUserName))
1873 if (uidp && uidp->unp)
1874 cm_ClientStrCpy(temp, lengthof(temp), uidp->unp->name);
1876 cm_ClientStrCpy(temp, lengthof(temp), _C(" "));
1877 cm_ClientStrLwr(temp);
1878 smb_subst(p, cchlen, var, lengthof(VNLCUserName), temp);
1880 else if (var = smb_stristr(p, VNComputerName))
1882 sizeTemp = lengthof(temp);
1883 GetComputerNameW(temp, &sizeTemp);
1884 smb_subst(p, cchlen, var, lengthof(VNComputerName), temp);
1886 else if (var = smb_stristr(p, VNLCComputerName))
1888 sizeTemp = lengthof(temp);
1889 GetComputerName((LPTSTR)temp, &sizeTemp);
1890 cm_ClientStrLwr(temp);
1891 smb_subst(p, cchlen, var, lengthof(VNLCComputerName), temp);
1896 *pathNamep = cm_ClientStrDup(p);
1901 /* First lookup shareName in root.afs */
1903 smb_findShare_rock_t vrock;
1905 fschar_t ftemp[1024];
1906 clientchar_t * p = shareName;
1909 /* attempt to locate a partial match in root.afs. This is because
1910 when using the ANSI RAP calls, the share name is limited to 13 chars
1911 and hence is truncated. Of course we prefer exact matches. */
1913 thyper.HighPart = 0;
1916 vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
1917 if (vrock.shareName == NULL)
1920 vrock.matchType = 0;
1922 cm_HoldSCache(cm_data.rootSCachep);
1923 code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
1924 (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
1925 cm_ReleaseSCache(cm_data.rootSCachep);
1927 free(vrock.shareName);
1928 vrock.shareName = NULL;
1930 if (vrock.matchType) {
1931 cm_ClientStrPrintfN(pathName, lengthof(pathName), _C("/%s/"), vrock.match);
1932 *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
1937 /* if we get here, there was no match for the share in root.afs */
1938 /* so try to create \\<netbiosName>\<cellname> */
1943 /* Get the full name for this cell */
1944 cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
1945 code = cm_SearchCellRegistry(1, cellname, ftemp, 0, 0, 0);
1946 if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
1947 code = cm_SearchCellFile(cellname, ftemp, 0, 0);
1948 #ifdef AFS_AFSDB_ENV
1949 if (code && cm_dnsEnabled) {
1951 code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
1957 /* construct the path */
1959 clientchar_t temp[1024];
1961 if (cm_FsStringToClientString(ftemp, -1, temp, 1024) != 0) {
1962 cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
1963 rw ? _C("/.%S/") : _C("/%S/"), temp);
1964 *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
1974 /* Client-side offline caching policy types */
1975 #define CSC_POLICY_MANUAL 0
1976 #define CSC_POLICY_DOCUMENTS 1
1977 #define CSC_POLICY_PROGRAMS 2
1978 #define CSC_POLICY_DISABLE 3
1980 int smb_FindShareCSCPolicy(clientchar_t *shareName)
1983 clientchar_t policy[1024];
1986 int retval = CSC_POLICY_MANUAL;
1988 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1989 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
1992 REG_OPTION_NON_VOLATILE,
1996 NULL ) != ERROR_SUCCESS)
1997 retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
1999 len = sizeof(policy);
2000 if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
2002 retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
2004 else if (cm_ClientStrCmpIA(policy, _C("manual")) == 0)
2006 retval = CSC_POLICY_MANUAL;
2008 else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
2010 retval = CSC_POLICY_DOCUMENTS;
2012 else if (cm_ClientStrCmpIA(policy, _C("programs")) == 0)
2014 retval = CSC_POLICY_PROGRAMS;
2016 else if (cm_ClientStrCmpIA(policy, _C("disable")) == 0)
2018 retval = CSC_POLICY_DISABLE;
2021 RegCloseKey(hkCSCPolicy);
2025 /* find a dir search structure by cookie value, and return it held.
2026 * Must be called with smb_globalLock held.
2028 smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
2030 smb_dirSearch_t *dsp;
2032 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
2033 if (dsp->cookie == cookie) {
2034 if (dsp != smb_firstDirSearchp) {
2035 /* move to head of LRU queue, too, if we're not already there */
2036 if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
2037 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
2038 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2039 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2040 if (!smb_lastDirSearchp)
2041 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
2049 osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
2050 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
2051 osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
2057 void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
2059 lock_ObtainMutex(&dsp->mx);
2060 osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p",
2061 dsp->cookie, dsp, dsp->scp);
2062 dsp->flags |= SMB_DIRSEARCH_DELETE;
2063 if (dsp->scp != NULL) {
2064 lock_ObtainWrite(&dsp->scp->rw);
2065 if (dsp->flags & SMB_DIRSEARCH_BULKST) {
2066 dsp->flags &= ~SMB_DIRSEARCH_BULKST;
2067 dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
2068 dsp->scp->bulkStatProgress = hzero;
2070 lock_ReleaseWrite(&dsp->scp->rw);
2072 lock_ReleaseMutex(&dsp->mx);
2075 /* Must be called with the smb_globalLock held */
2076 void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
2078 cm_scache_t *scp = NULL;
2080 osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
2081 if (dsp->refCount == 0) {
2082 lock_ObtainMutex(&dsp->mx);
2083 if (dsp->flags & SMB_DIRSEARCH_DELETE) {
2084 if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
2085 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
2086 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2087 lock_ReleaseMutex(&dsp->mx);
2088 lock_FinalizeMutex(&dsp->mx);
2090 osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
2091 dsp->cookie, dsp, scp);
2094 lock_ReleaseMutex(&dsp->mx);
2097 /* do this now to avoid spurious locking hierarchy creation */
2099 cm_ReleaseSCache(scp);
2102 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
2104 lock_ObtainWrite(&smb_globalLock);
2105 smb_ReleaseDirSearchNoLock(dsp);
2106 lock_ReleaseWrite(&smb_globalLock);
2109 /* find a dir search structure by cookie value, and return it held */
2110 smb_dirSearch_t *smb_FindDirSearch(long cookie)
2112 smb_dirSearch_t *dsp;
2114 lock_ObtainWrite(&smb_globalLock);
2115 dsp = smb_FindDirSearchNoLock(cookie);
2116 lock_ReleaseWrite(&smb_globalLock);
2120 /* GC some dir search entries, in the address space expected by the specific protocol.
2121 * Must be called with smb_globalLock held; release the lock temporarily.
2123 #define SMB_DIRSEARCH_GCMAX 10 /* how many at once */
2124 void smb_GCDirSearches(int isV3)
2126 smb_dirSearch_t *prevp;
2127 smb_dirSearch_t *dsp;
2128 smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
2132 victimCount = 0; /* how many have we got so far */
2133 for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
2134 /* we'll move tp from queue, so
2137 prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
2138 /* if no one is using this guy, and we're either in the new protocol,
2139 * or we're in the old one and this is a small enough ID to be useful
2140 * to the old protocol, GC this guy.
2142 if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
2143 /* hold and delete */
2144 lock_ObtainMutex(&dsp->mx);
2145 dsp->flags |= SMB_DIRSEARCH_DELETE;
2146 lock_ReleaseMutex(&dsp->mx);
2147 victimsp[victimCount++] = dsp;
2151 /* don't do more than this */
2152 if (victimCount >= SMB_DIRSEARCH_GCMAX)
2156 /* now release them */
2157 for (i = 0; i < victimCount; i++) {
2158 smb_ReleaseDirSearchNoLock(victimsp[i]);
2162 /* function for allocating a dir search entry. We need these to remember enough context
2163 * since we don't get passed the path from call to call during a directory search.
2165 * Returns a held dir search structure, and bumps the reference count on the vnode,
2166 * since it saves a pointer to the vnode.
2168 smb_dirSearch_t *smb_NewDirSearch(int isV3)
2170 smb_dirSearch_t *dsp;
2176 lock_ObtainWrite(&smb_globalLock);
2179 /* what's the biggest ID allowed in this version of the protocol */
2180 /* TODO: do we really want a non v3 dir search request to wrap
2181 smb_dirSearchCounter? */
2182 maxAllowed = isV3 ? 65535 : 255;
2183 if (smb_dirSearchCounter > maxAllowed)
2184 smb_dirSearchCounter = 1;
2186 start = smb_dirSearchCounter;
2189 /* twice so we have enough tries to find guys we GC after one pass;
2190 * 10 extra is just in case I mis-counted.
2192 if (++counter > 2*maxAllowed+10)
2193 osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
2195 if (smb_dirSearchCounter > maxAllowed) {
2196 smb_dirSearchCounter = 1;
2198 if (smb_dirSearchCounter == start) {
2200 smb_GCDirSearches(isV3);
2203 dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
2205 /* don't need to watch for refcount zero and deleted, since
2206 * we haven't dropped the global lock.
2209 ++smb_dirSearchCounter;
2213 dsp = malloc(sizeof(*dsp));
2214 memset(dsp, 0, sizeof(*dsp));
2215 dsp->cookie = smb_dirSearchCounter;
2216 ++smb_dirSearchCounter;
2218 lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
2219 dsp->lastTime = osi_Time();
2220 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
2221 if (!smb_lastDirSearchp)
2222 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
2224 osi_Log2(smb_logp,"smb_NewDirSearch cookie %d dsp 0x%p",
2228 lock_ReleaseWrite(&smb_globalLock);
2232 static smb_packet_t *smb_GetPacket(void)
2236 lock_ObtainWrite(&smb_globalLock);
2237 tbp = smb_packetFreeListp;
2239 smb_packetFreeListp = tbp->nextp;
2240 lock_ReleaseWrite(&smb_globalLock);
2242 tbp = calloc(sizeof(*tbp),1);
2243 tbp->magic = SMB_PACKETMAGIC;
2246 tbp->resumeCode = 0;
2252 tbp->ncb_length = 0;
2255 tbp->stringsp = NULL;
2257 osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
2262 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
2265 tbp = smb_GetPacket();
2266 memcpy(tbp, pkt, sizeof(smb_packet_t));
2267 tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
2268 tbp->stringsp = NULL;
2270 smb_HoldVC(tbp->vcp);
2274 static NCB *smb_GetNCB(void)
2279 lock_ObtainWrite(&smb_globalLock);
2280 tbp = smb_ncbFreeListp;
2282 smb_ncbFreeListp = tbp->nextp;
2283 lock_ReleaseWrite(&smb_globalLock);
2285 tbp = calloc(sizeof(*tbp),1);
2286 tbp->magic = SMB_NCBMAGIC;
2289 osi_assertx(tbp->magic == SMB_NCBMAGIC, "invalid smb_packet_t magic");
2291 memset(&tbp->ncb, 0, sizeof(NCB));
2296 static void FreeSMBStrings(smb_packet_t * pkt)
2301 for (s = pkt->stringsp; s; s = ns) {
2305 pkt->stringsp = NULL;
2308 void smb_FreePacket(smb_packet_t *tbp)
2310 smb_vc_t * vcp = NULL;
2311 osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
2313 lock_ObtainWrite(&smb_globalLock);
2314 tbp->nextp = smb_packetFreeListp;
2315 smb_packetFreeListp = tbp;
2316 tbp->magic = SMB_PACKETMAGIC;
2320 tbp->resumeCode = 0;
2326 tbp->ncb_length = 0;
2328 FreeSMBStrings(tbp);
2329 lock_ReleaseWrite(&smb_globalLock);
2335 static void smb_FreeNCB(NCB *bufferp)
2339 tbp = (smb_ncb_t *) bufferp;
2340 osi_assertx(tbp->magic == SMB_NCBMAGIC, "invalid smb_packet_t magic");
2342 lock_ObtainWrite(&smb_globalLock);
2343 tbp->nextp = smb_ncbFreeListp;
2344 smb_ncbFreeListp = tbp;
2345 lock_ReleaseWrite(&smb_globalLock);
2348 /* get a ptr to the data part of a packet, and its count */
2349 unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
2353 unsigned char *afterParmsp;
2355 parmBytes = *smbp->wctp << 1;
2356 afterParmsp = smbp->wctp + parmBytes + 1;
2358 dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
2359 if (nbytesp) *nbytesp = dataBytes;
2361 /* don't forget to skip the data byte count, since it follows
2362 * the parameters; that's where the "2" comes from below.
2364 return (unsigned char *) (afterParmsp + 2);
2367 /* must set all the returned parameters before playing around with the
2368 * data region, since the data region is located past the end of the
2369 * variable number of parameters.
2371 void smb_SetSMBDataLength(smb_packet_t *smbp, unsigned int dsize)
2373 unsigned char *afterParmsp;
2375 afterParmsp = smbp->wctp + ((*smbp->wctp)<<1) + 1;
2377 *afterParmsp++ = dsize & 0xff;
2378 *afterParmsp = (dsize>>8) & 0xff;
2381 /* return the parm'th parameter in the smbp packet */
2382 unsigned short smb_GetSMBParm(smb_packet_t *smbp, int parm)
2385 unsigned char *parmDatap;
2387 parmCount = *smbp->wctp;
2389 if (parm >= parmCount) {
2392 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2393 parm, parmCount, smbp->ncb_length);
2394 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2395 parm, parmCount, smbp->ncb_length);
2396 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2397 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2398 osi_panic(s, __FILE__, __LINE__);
2400 parmDatap = smbp->wctp + (2*parm) + 1;
2402 return parmDatap[0] + (parmDatap[1] << 8);
2405 /* return the parm'th parameter in the smbp packet */
2406 unsigned char smb_GetSMBParmByte(smb_packet_t *smbp, int parm)
2409 unsigned char *parmDatap;
2411 parmCount = *smbp->wctp;
2413 if (parm >= parmCount) {
2416 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2417 parm, parmCount, smbp->ncb_length);
2418 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2419 parm, parmCount, smbp->ncb_length);
2420 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2421 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2422 osi_panic(s, __FILE__, __LINE__);
2424 parmDatap = smbp->wctp + (2*parm) + 1;
2426 return parmDatap[0];
2429 /* return the parm'th parameter in the smbp packet */
2430 unsigned int smb_GetSMBParmLong(smb_packet_t *smbp, int parm)
2433 unsigned char *parmDatap;
2435 parmCount = *smbp->wctp;
2437 if (parm + 1 >= parmCount) {
2440 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2441 parm, parmCount, smbp->ncb_length);
2442 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2443 parm, parmCount, smbp->ncb_length);
2444 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2445 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2446 osi_panic(s, __FILE__, __LINE__);
2448 parmDatap = smbp->wctp + (2*parm) + 1;
2450 return parmDatap[0] + (parmDatap[1] << 8) + (parmDatap[2] << 16) + (parmDatap[3] << 24);
2453 /* return the parm'th parameter in the smbp packet */
2454 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
2457 unsigned char *parmDatap;
2459 parmCount = *smbp->wctp;
2461 if (parm * 2 + offset >= parmCount * 2) {
2464 sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
2465 parm, offset, parmCount, smbp->ncb_length);
2466 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET,
2467 __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
2468 osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
2469 parm, offset, parmCount, smbp->ncb_length);
2470 osi_panic(s, __FILE__, __LINE__);
2472 parmDatap = smbp->wctp + (2*parm) + 1 + offset;
2474 return parmDatap[0] + (parmDatap[1] << 8);
2477 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
2479 unsigned char *parmDatap;
2481 /* make sure we have enough slots */
2482 if (*smbp->wctp <= slot)
2483 *smbp->wctp = slot+1;
2485 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2486 *parmDatap++ = parmValue & 0xff;
2487 *parmDatap = (parmValue>>8) & 0xff;
2490 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
2492 unsigned char *parmDatap;
2494 /* make sure we have enough slots */
2495 if (*smbp->wctp <= slot)
2496 *smbp->wctp = slot+2;
2498 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2499 *parmDatap++ = parmValue & 0xff;
2500 *parmDatap++ = (parmValue>>8) & 0xff;
2501 *parmDatap++ = (parmValue>>16) & 0xff;
2502 *parmDatap = (parmValue>>24) & 0xff;
2505 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
2507 unsigned char *parmDatap;
2510 /* make sure we have enough slots */
2511 if (*smbp->wctp <= slot)
2512 *smbp->wctp = slot+4;
2514 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2516 *parmDatap++ = *parmValuep++;
2519 void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
2521 unsigned char *parmDatap;
2523 /* make sure we have enough slots */
2524 if (*smbp->wctp <= slot) {
2525 if (smbp->oddByte) {
2527 *smbp->wctp = slot+1;
2532 parmDatap = smbp->wctp + 2*slot + 1 + (1 - smbp->oddByte);
2533 *parmDatap++ = parmValue & 0xff;
2538 void smb_StripLastComponent(clientchar_t *outPathp, clientchar_t **lastComponentp,
2539 clientchar_t *inPathp)
2541 clientchar_t *lastSlashp;
2542 clientchar_t *streamp = NULL;
2543 clientchar_t *typep = NULL;
2545 lastSlashp = cm_ClientStrRChr(inPathp, '\\');
2546 if (lastComponentp) {
2547 *lastComponentp = lastSlashp;
2551 * If the name contains a stream name and a type
2552 * and the stream name is the nul-string and the
2553 * type is $DATA, then strip "::$DATA" from the
2554 * last component string that is returned.
2556 * Otherwise, return the full path name and allow
2557 * the file name to be rejected because it contains
2560 typep = cm_ClientStrRChr(lastSlashp, L':');
2561 if (typep && cm_ClientStrCmpI(typep, L":$DATA") == 0) {
2563 streamp = cm_ClientStrRChr(lastSlashp, L':');
2564 if (streamp && cm_ClientStrCmpI(streamp, L":") == 0) {
2568 osi_Log2(smb_logp, "smb_StripLastComponent found stream [%S] type [%S]",
2569 osi_LogSaveClientString(smb_logp,streamp),
2570 osi_LogSaveClientString(smb_logp,typep));
2574 if (inPathp == lastSlashp)
2576 *outPathp++ = *inPathp++;
2585 clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
2586 char **chainpp, int flags)
2589 afs_uint32 type = *inp++;
2592 * The first byte specifies the type of the input string.
2593 * CIFS TR 1.0 3.2.10. This function only parses null terminated
2597 /* Length Counted */
2598 case 0x1: /* Data Block */
2599 case 0x5: /* Variable Block */
2600 cb = *inp++ << 16 | *inp++;
2603 /* Null-terminated string */
2604 case 0x4: /* ASCII */
2605 case 0x3: /* Pathname */
2606 case 0x2: /* Dialect */
2607 cb = sizeof(pktp->data) - (inp - pktp->data);
2608 if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
2609 #ifdef DEBUG_UNICODE
2612 cb = sizeof(pktp->data);
2617 return NULL; /* invalid input */
2621 if (type == 0x2 /* Dialect */ || !WANTS_UNICODE(pktp))
2622 flags |= SMB_STRF_FORCEASCII;
2625 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2628 clientchar_t *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
2629 char ** chainpp, int flags)
2634 if (!WANTS_UNICODE(pktp))
2635 flags |= SMB_STRF_FORCEASCII;
2638 cb = sizeof(pktp->data) - (inp - pktp->data);
2639 if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
2640 #ifdef DEBUG_UNICODE
2643 cb = sizeof(pktp->data);
2645 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
2646 flags | SMB_STRF_SRCNULTERM);
2649 clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
2650 size_t cb, char ** chainpp, int flags)
2653 if (!WANTS_UNICODE(pktp))
2654 flags |= SMB_STRF_FORCEASCII;
2657 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2660 clientchar_t *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp,
2661 size_t cch, char ** chainpp, int flags)
2666 if (!WANTS_UNICODE(pktp))
2667 flags |= SMB_STRF_FORCEASCII;
2669 cb = cch * sizeof(wchar_t);
2672 return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
2676 smb_ParseStringBuf(const unsigned char * bufbase,
2677 cm_space_t ** stringspp,
2678 unsigned char *inp, size_t *pcb_max,
2679 char **chainpp, int flags)
2682 if (!(flags & SMB_STRF_FORCEASCII)) {
2684 cm_space_t * spacep;
2687 if (bufbase && ((inp - bufbase) % 2) != 0) {
2688 inp++; /* unicode strings are always word aligned */
2692 if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t),
2694 cch_src = *pcb_max / sizeof(wchar_t);
2698 *pcb_max -= (cch_src + 1) * sizeof(wchar_t);
2705 spacep = cm_GetSpace();
2706 spacep->nextp = *stringspp;
2707 *stringspp = spacep;
2711 *chainpp = inp + sizeof(wchar_t);
2714 *(spacep->wdata) = 0;
2715 return spacep->wdata;
2718 StringCchCopyNW(spacep->wdata,
2719 lengthof(spacep->wdata),
2720 (const clientchar_t *) inp, cch_src);
2723 *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t);
2725 return spacep->wdata;
2729 cm_space_t * spacep;
2732 /* Not using Unicode */
2734 *chainpp = inp + strlen(inp) + 1;
2737 spacep = cm_GetSpace();
2738 spacep->nextp = *stringspp;
2739 *stringspp = spacep;
2741 cchdest = lengthof(spacep->wdata);
2742 cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
2743 spacep->wdata, cchdest);
2745 return spacep->wdata;
2751 unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
2753 size_t * plen, int flags)
2759 /* we are only calculating the required size */
2766 if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
2768 StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
2769 if (!(flags & SMB_STRF_IGNORENUL))
2770 *plen += sizeof(wchar_t);
2772 return (unsigned char *) 1; /* return TRUE if we are using unicode */
2782 cch_str = cm_ClientStrLen(str);
2783 cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
2786 *plen = ((flags & SMB_STRF_IGNORENUL)? cch_dest: cch_dest+1);
2794 /* if outp != NULL ... */
2796 /* Number of bytes left in the buffer.
2798 If outp lies inside the packet data buffer, we assume that the
2799 buffer is the packet data buffer. Otherwise we assume that the
2800 buffer is sizeof(packet->data).
2803 if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
2804 align = (int)((outp - pktp->data) % 2);
2805 buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
2807 align = (int)(((size_t) outp) % 2);
2808 buffersize = (int)sizeof(pktp->data);
2813 if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
2819 if (*str == _C('\0')) {
2821 if (buffersize < sizeof(wchar_t))
2824 *((wchar_t *) outp) = L'\0';
2825 if (plen && !(flags & SMB_STRF_IGNORENUL))
2826 *plen += sizeof(wchar_t);
2827 return outp + sizeof(wchar_t);
2830 nchars = cm_ClientStringToUtf16(str, -1, (wchar_t *) outp, (int)(buffersize / sizeof(wchar_t)));
2832 osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
2833 osi_LogSaveClientString(smb_logp, str),
2839 *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENUL)? nchars - 1: nchars);
2841 return outp + sizeof(wchar_t) * nchars;
2849 cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
2852 *plen += ((flags & SMB_STRF_IGNORENUL)? cch_dest - 1: cch_dest);
2854 return outp + cch_dest;
2858 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
2864 tlen = inp[0] + (inp[1]<<8);
2865 inp += 2; /* skip length field */
2868 *chainpp = inp + tlen;
2877 unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
2881 if (*inp++ != 0x1) return NULL;
2882 tlen = inp[0] + (inp[1]<<8);
2883 inp += 2; /* skip length field */
2886 *chainpp = inp + tlen;
2889 if (lengthp) *lengthp = tlen;
2894 /* format a packet as a response */
2895 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
2900 outp = (smb_t *) op;
2902 /* zero the basic structure through the smb_wct field, and zero the data
2903 * size field, assuming that wct stays zero; otherwise, you have to
2904 * explicitly set the data size field, too.
2906 inSmbp = (smb_t *) inp;
2907 memset(outp, 0, sizeof(smb_t)+2);
2913 outp->com = inSmbp->com;
2914 outp->tid = inSmbp->tid;
2915 outp->pid = inSmbp->pid;
2916 outp->uid = inSmbp->uid;
2917 outp->mid = inSmbp->mid;
2918 outp->res[0] = inSmbp->res[0];
2919 outp->res[1] = inSmbp->res[1];
2920 op->inCom = inSmbp->com;
2922 outp->reb = SMB_FLAGS_SERVER_TO_CLIENT;
2923 #ifdef SEND_CANONICAL_PATHNAMES
2924 outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
2926 outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
2928 if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
2929 outp->flg2 |= SMB_FLAGS2_UNICODE;
2932 /* copy fields in generic packet area */
2933 op->wctp = &outp->wct;
2936 /* send a (probably response) packet; vcp tells us to whom to send it.
2937 * we compute the length by looking at wct and bcc fields.
2939 void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
2949 ncbp = smb_GetNCB();
2953 memset((char *)ncbp, 0, sizeof(NCB));
2955 extra = 2 * (*inp->wctp); /* space used by parms, in bytes */
2956 tp = inp->wctp + 1+ extra; /* points to count of data bytes */
2957 extra += tp[0] + (tp[1]<<8);
2958 extra += (unsigned int)(inp->wctp - inp->data); /* distance to last wct field */
2959 extra += 3; /* wct and length fields */
2961 ncbp->ncb_length = extra; /* bytes to send */
2962 ncbp->ncb_lsn = (unsigned char) vcp->lsn; /* vc to use */
2963 ncbp->ncb_lana_num = vcp->lana;
2964 ncbp->ncb_command = NCBSEND; /* op means send data */
2965 ncbp->ncb_buffer = (char *) inp;/* packet */
2966 code = Netbios(ncbp);
2969 const char * s = ncb_error_string(code);
2970 osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
2971 LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
2973 lock_ObtainMutex(&vcp->mx);
2974 if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
2975 osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
2977 vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
2978 lock_ReleaseMutex(&vcp->mx);
2979 lock_ObtainWrite(&smb_globalLock);
2980 dead_sessions[vcp->session] = TRUE;
2981 lock_ReleaseWrite(&smb_globalLock);
2982 smb_CleanupDeadVC(vcp);
2984 lock_ReleaseMutex(&vcp->mx);
2992 void smb_MapNTError(long code, unsigned long *NTStatusp)
2994 unsigned long NTStatus;
2996 /* map CM_ERROR_* errors to NT 32-bit status codes */
2997 /* NT Status codes are listed in ntstatus.h not winerror.h */
3001 else if (code == CM_ERROR_NOSUCHCELL) {
3002 NTStatus = 0xC0000034L; /* Name not found */
3004 else if (code == CM_ERROR_NOSUCHVOLUME) {
3005 NTStatus = 0xC0000034L; /* Name not found */
3007 else if (code == CM_ERROR_TIMEDOUT) {
3009 NTStatus = 0xC00000CFL; /* Sharing Paused */
3011 /* Do not send Timeout to the SMB redirector.
3012 * It causes the redirector to drop the connection */
3013 NTStatus = 0x00000102L; /* Timeout */
3015 NTStatus = 0xC000022DL; /* Retry */
3018 else if (code == CM_ERROR_RETRY) {
3019 NTStatus = 0xC000022DL; /* Retry */
3021 else if (code == CM_ERROR_NOACCESS) {
3022 NTStatus = 0xC0000022L; /* Access denied */
3024 else if (code == CM_ERROR_READONLY) {
3025 NTStatus = 0xC00000A2L; /* Write protected */
3027 else if (code == CM_ERROR_NOSUCHFILE ||
3028 code == CM_ERROR_BPLUS_NOMATCH) {
3029 NTStatus = 0xC0000034L; /* Name not found */
3031 else if (code == CM_ERROR_NOSUCHPATH) {
3032 NTStatus = 0xC000003AL; /* Object path not found */
3034 else if (code == CM_ERROR_TOOBIG) {
3035 NTStatus = 0xC000007BL; /* Invalid image format */
3037 else if (code == CM_ERROR_INVAL) {
3038 NTStatus = 0xC000000DL; /* Invalid parameter */
3040 else if (code == CM_ERROR_BADFD) {
3041 NTStatus = 0xC0000008L; /* Invalid handle */
3043 else if (code == CM_ERROR_BADFDOP) {
3044 NTStatus = 0xC0000022L; /* Access denied */
3046 else if (code == CM_ERROR_UNKNOWN) {
3047 NTStatus = 0xC0000022L; /* Access denied */
3049 else if (code == CM_ERROR_EXISTS) {
3050 NTStatus = 0xC0000035L; /* Object name collision */
3052 else if (code == CM_ERROR_NOTEMPTY) {
3053 NTStatus = 0xC0000101L; /* Directory not empty */
3055 else if (code == CM_ERROR_CROSSDEVLINK) {
3056 NTStatus = 0xC00000D4L; /* Not same device */
3058 else if (code == CM_ERROR_NOTDIR) {
3059 NTStatus = 0xC0000103L; /* Not a directory */
3061 else if (code == CM_ERROR_ISDIR) {
3062 NTStatus = 0xC00000BAL; /* File is a directory */
3064 else if (code == CM_ERROR_BADOP) {
3066 /* I have no idea where this comes from */
3067 NTStatus = 0xC09820FFL; /* SMB no support */
3069 NTStatus = 0xC00000BBL; /* Not supported */
3070 #endif /* COMMENT */
3072 else if (code == CM_ERROR_BADSHARENAME) {
3073 NTStatus = 0xC00000BEL; /* Bad network path (server valid, share bad) */
3075 else if (code == CM_ERROR_NOIPC) {
3077 NTStatus = 0xC0000022L; /* Access Denied */
3079 NTStatus = 0xC000013DL; /* Remote Resources */
3082 else if (code == CM_ERROR_CLOCKSKEW ||
3083 code == RXKADNOAUTH) {
3084 NTStatus = 0xC0000133L; /* Time difference at DC */
3086 else if (code == CM_ERROR_BADTID) {
3087 NTStatus = 0xC0982005L; /* SMB bad TID */
3089 else if (code == CM_ERROR_USESTD) {
3090 NTStatus = 0xC09820FBL; /* SMB use standard */
3092 else if (code == CM_ERROR_QUOTA) {
3093 NTStatus = 0xC0000044L; /* Quota exceeded */
3095 else if (code == CM_ERROR_SPACE) {
3096 NTStatus = 0xC000007FL; /* Disk full */
3098 else if (code == CM_ERROR_ATSYS) {
3099 NTStatus = 0xC0000033L; /* Object name invalid */
3101 else if (code == CM_ERROR_BADNTFILENAME) {
3102 NTStatus = 0xC0000033L; /* Object name invalid */
3104 else if (code == CM_ERROR_WOULDBLOCK) {
3105 NTStatus = 0xC00000D8L; /* Can't wait */
3107 else if (code == CM_ERROR_SHARING_VIOLATION) {
3108 NTStatus = 0xC0000043L; /* Sharing violation */
3110 else if (code == CM_ERROR_LOCK_CONFLICT) {
3111 NTStatus = 0xC0000054L; /* Lock conflict */
3113 else if (code == CM_ERROR_PARTIALWRITE) {
3114 NTStatus = 0xC000007FL; /* Disk full */
3116 else if (code == CM_ERROR_BUFFERTOOSMALL) {
3117 NTStatus = 0xC0000023L; /* Buffer too small */
3119 else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
3120 NTStatus = 0xC0000035L; /* Object name collision */
3122 else if (code == CM_ERROR_BADPASSWORD) {
3123 NTStatus = 0xC000006DL; /* unknown username or bad password */
3125 else if (code == CM_ERROR_BADLOGONTYPE) {
3126 NTStatus = 0xC000015BL; /* logon type not granted */
3128 else if (code == CM_ERROR_GSSCONTINUE) {
3129 NTStatus = 0xC0000016L; /* more processing required */
3131 else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
3133 NTStatus = 0xC0000280L; /* reparse point not resolved */
3135 NTStatus = 0xC0000022L; /* Access Denied */
3138 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3139 NTStatus = 0xC0000257L; /* Path Not Covered */
3141 else if (code == CM_ERROR_ALLBUSY) {
3142 NTStatus = 0xC000022DL; /* Retry */
3144 else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
3145 NTStatus = 0xC000003AL; /* Path not found */
3147 else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
3148 NTStatus = 0xC0000322L; /* No Kerberos key */
3150 else if (code == CM_ERROR_BAD_LEVEL) {
3151 NTStatus = 0xC0000148L; /* Invalid Level */
3153 else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
3154 NTStatus = 0xC000007EL; /* Range Not Locked */
3156 else if (code == CM_ERROR_NOSUCHDEVICE) {
3157 NTStatus = 0xC000000EL; /* No Such Device */
3159 else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
3160 NTStatus = 0xC0000055L; /* Lock Not Granted */
3162 else if (code == ENOMEM) {
3163 NTStatus = 0xC0000017L; /* Out of Memory */
3165 else if (code == CM_ERROR_RPC_MOREDATA) {
3166 NTStatus = 0x80000005L; /* Buffer overflow */
3169 NTStatus = 0xC0982001L; /* SMB non-specific error */
3172 *NTStatusp = NTStatus;
3173 osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
3177 * NTSTATUS <-> Win32 Error Translation
3178 * http://support.microsoft.com/kb/113996
3180 void smb_MapWin32Error(long code, unsigned long *Win32Ep)
3182 unsigned long Win32E;
3184 /* map CM_ERROR_* errors to Win32 32-bit error codes */
3188 else if (code == CM_ERROR_NOSUCHCELL) {
3189 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3191 else if (code == CM_ERROR_NOSUCHVOLUME) {
3192 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3194 else if (code == CM_ERROR_TIMEDOUT) {
3196 Win32E = ERROR_SHARING_PAUSED; /* Sharing Paused */
3198 Win32E = ERROR_UNEXP_NET_ERR; /* Timeout */
3201 else if (code == CM_ERROR_RETRY) {
3202 Win32E = ERROR_RETRY; /* Retry */
3204 else if (code == CM_ERROR_NOACCESS) {
3205 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3207 else if (code == CM_ERROR_READONLY) {
3208 Win32E = ERROR_WRITE_PROTECT; /* Write protected */
3210 else if (code == CM_ERROR_NOSUCHFILE ||
3211 code == CM_ERROR_BPLUS_NOMATCH) {
3212 Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
3214 else if (code == CM_ERROR_NOSUCHPATH) {
3215 Win32E = ERROR_PATH_NOT_FOUND; /* Object path not found */
3217 else if (code == CM_ERROR_TOOBIG) {
3218 Win32E = ERROR_BAD_EXE_FORMAT; /* Invalid image format */
3220 else if (code == CM_ERROR_INVAL) {
3221 Win32E = ERROR_INVALID_PARAMETER;/* Invalid parameter */
3223 else if (code == CM_ERROR_BADFD) {
3224 Win32E = ERROR_INVALID_HANDLE; /* Invalid handle */
3226 else if (code == CM_ERROR_BADFDOP) {
3227 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3229 else if (code == CM_ERROR_UNKNOWN) {
3230 Win32E = ERROR_ACCESS_DENIED; /* Access denied */
3232 else if (code == CM_ERROR_EXISTS) {
3233 Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
3235 else if (code == CM_ERROR_NOTEMPTY) {
3236 Win32E = ERROR_DIR_NOT_EMPTY; /* Directory not empty */
3238 else if (code == CM_ERROR_CROSSDEVLINK) {
3239 Win32E = ERROR_NOT_SAME_DEVICE; /* Not same device */
3241 else if (code == CM_ERROR_NOTDIR) {
3242 Win32E = ERROR_DIRECTORY; /* Not a directory */
3244 else if (code == CM_ERROR_ISDIR) {
3245 Win32E = ERROR_ACCESS_DENIED; /* File is a directory */
3247 else if (code == CM_ERROR_BADOP) {
3248 Win32E = ERROR_NOT_SUPPORTED; /* Not supported */
3250 else if (code == CM_ERROR_BADSHARENAME) {
3251 Win32E = ERROR_BAD_NETPATH; /* Bad network path (server valid, share bad) */
3253 else if (code == CM_ERROR_NOIPC) {
3255 Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
3257 Win32E = ERROR_REM_NOT_LIST; /* Remote Resources */
3260 else if (code == CM_ERROR_CLOCKSKEW ||
3261 code == RXKADNOAUTH) {
3262 Win32E = ERROR_TIME_SKEW; /* Time difference at DC */
3264 else if (code == CM_ERROR_BADTID) {
3265 Win32E = ERROR_FILE_NOT_FOUND; /* SMB bad TID */
3267 else if (code == CM_ERROR_USESTD) {
3268 Win32E = ERROR_ACCESS_DENIED; /* SMB use standard */
3270 else if (code == CM_ERROR_QUOTA) {
3271 Win32E = ERROR_NOT_ENOUGH_QUOTA;/* Quota exceeded */
3273 else if (code == CM_ERROR_SPACE) {
3274 Win32E = ERROR_DISK_FULL; /* Disk full */
3276 else if (code == CM_ERROR_ATSYS) {
3277 Win32E = ERROR_INVALID_NAME; /* Object name invalid */
3279 else if (code == CM_ERROR_BADNTFILENAME) {
3280 Win32E = ERROR_INVALID_NAME; /* Object name invalid */
3282 else if (code == CM_ERROR_WOULDBLOCK) {
3283 Win32E = WAIT_TIMEOUT; /* Can't wait */
3285 else if (code == CM_ERROR_SHARING_VIOLATION) {
3286 Win32E = ERROR_SHARING_VIOLATION; /* Sharing violation */
3288 else if (code == CM_ERROR_LOCK_CONFLICT) {
3289 Win32E = ERROR_LOCK_VIOLATION; /* Lock conflict */
3291 else if (code == CM_ERROR_PARTIALWRITE) {
3292 Win32E = ERROR_DISK_FULL; /* Disk full */
3294 else if (code == CM_ERROR_BUFFERTOOSMALL) {
3295 Win32E = ERROR_INSUFFICIENT_BUFFER; /* Buffer too small */
3297 else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
3298 Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
3300 else if (code == CM_ERROR_BADPASSWORD) {
3301 Win32E = ERROR_LOGON_FAILURE; /* unknown username or bad password */
3303 else if (code == CM_ERROR_BADLOGONTYPE) {
3304 Win32E = ERROR_INVALID_LOGON_TYPE; /* logon type not granted */
3306 else if (code == CM_ERROR_GSSCONTINUE) {
3307 Win32E = ERROR_MORE_DATA; /* more processing required */
3309 else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
3311 Win32E = ERROR_CANT_RESOLVE_FILENAME; /* reparse point not resolved */
3313 Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
3316 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3317 Win32E = ERROR_HOST_UNREACHABLE; /* Path Not Covered */
3319 else if (code == CM_ERROR_ALLBUSY) {
3320 Win32E = ERROR_RETRY; /* Retry */
3322 else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
3323 Win32E = ERROR_HOST_UNREACHABLE; /* Path not found */
3325 else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
3326 Win32E = SEC_E_NO_KERB_KEY; /* No Kerberos key */
3328 else if (code == CM_ERROR_BAD_LEVEL) {
3329 Win32E = ERROR_INVALID_LEVEL; /* Invalid Level */
3331 else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
3332 Win32E = ERROR_NOT_LOCKED; /* Range Not Locked */
3334 else if (code == CM_ERROR_NOSUCHDEVICE) {
3335 Win32E = ERROR_FILE_NOT_FOUND; /* No Such Device */
3337 else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
3338 Win32E = ERROR_LOCK_VIOLATION; /* Lock Not Granted */
3340 else if (code == ENOMEM) {
3341 Win32E = ERROR_NOT_ENOUGH_MEMORY; /* Out of Memory */
3343 else if (code == CM_ERROR_RPC_MOREDATA) {
3344 Win32E = ERROR_MORE_DATA; /* Buffer overflow */
3347 Win32E = ERROR_GEN_FAILURE; /* SMB non-specific error */
3351 osi_Log2(smb_logp, "SMB SEND code %lX as Win32 %lX", code, Win32E);
3354 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
3355 unsigned char *classp)
3357 unsigned char class;
3358 unsigned short error;
3360 /* map CM_ERROR_* errors to SMB errors */
3361 if (code == CM_ERROR_NOSUCHCELL) {
3363 error = 3; /* bad path */
3365 else if (code == CM_ERROR_NOSUCHVOLUME) {
3367 error = 3; /* bad path */
3369 else if (code == CM_ERROR_TIMEDOUT) {
3371 error = 81; /* server is paused */
3373 else if (code == CM_ERROR_RETRY) {
3374 class = 2; /* shouldn't happen */
3377 else if (code == CM_ERROR_NOACCESS) {
3379 error = 4; /* bad access */
3381 else if (code == CM_ERROR_READONLY) {
3383 error = 19; /* read only */
3385 else if (code == CM_ERROR_NOSUCHFILE ||
3386 code == CM_ERROR_BPLUS_NOMATCH) {
3388 error = 2; /* ENOENT! */
3390 else if (code == CM_ERROR_NOSUCHPATH) {
3392 error = 3; /* Bad path */
3394 else if (code == CM_ERROR_TOOBIG) {
3396 error = 11; /* bad format */
3398 else if (code == CM_ERROR_INVAL) {
3399 class = 2; /* server non-specific error code */
3402 else if (code == CM_ERROR_BADFD) {
3404 error = 6; /* invalid file handle */
3406 else if (code == CM_ERROR_BADFDOP) {
3407 class = 1; /* invalid op on FD */
3410 else if (code == CM_ERROR_EXISTS) {
3412 error = 80; /* file already exists */
3414 else if (code == CM_ERROR_NOTEMPTY) {
3416 error = 5; /* delete directory not empty */
3418 else if (code == CM_ERROR_CROSSDEVLINK) {
3420 error = 17; /* EXDEV */
3422 else if (code == CM_ERROR_NOTDIR) {
3423 class = 1; /* bad path */
3426 else if (code == CM_ERROR_ISDIR) {
3427 class = 1; /* access denied; DOS doesn't have a good match */
3430 else if (code == CM_ERROR_BADOP) {
3434 else if (code == CM_ERROR_BADSHARENAME) {
3438 else if (code == CM_ERROR_NOIPC) {
3440 error = 4; /* bad access */
3442 else if (code == CM_ERROR_CLOCKSKEW) {
3443 class = 1; /* invalid function */
3446 else if (code == CM_ERROR_BADTID) {
3450 else if (code == CM_ERROR_USESTD) {
3454 else if (code == CM_ERROR_REMOTECONN) {
3458 else if (code == CM_ERROR_QUOTA) {
3459 if (vcp->flags & SMB_VCFLAG_USEV3) {
3461 error = 39; /* disk full */
3465 error = 5; /* access denied */
3468 else if (code == CM_ERROR_SPACE) {
3469 if (vcp->flags & SMB_VCFLAG_USEV3) {
3471 error = 39; /* disk full */
3475 error = 5; /* access denied */
3478 else if (code == CM_ERROR_PARTIALWRITE) {
3480 error = 39; /* disk full */
3482 else if (code == CM_ERROR_ATSYS) {
3484 error = 2; /* ENOENT */
3486 else if (code == CM_ERROR_WOULDBLOCK) {
3488 error = 33; /* lock conflict */
3490 else if (code == CM_ERROR_LOCK_CONFLICT) {
3492 error = 33; /* lock conflict */
3494 else if (code == CM_ERROR_SHARING_VIOLATION) {
3496 error = 33; /* lock conflict */
3498 else if (code == CM_ERROR_NOFILES) {
3500 error = 18; /* no files in search */
3502 else if (code == CM_ERROR_RENAME_IDENTICAL) {
3504 error = 183; /* Samba uses this */
3506 else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
3507 /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
3509 error = 2; /* bad password */
3511 else if (code == CM_ERROR_PATH_NOT_COVERED) {
3513 error = 3; /* bad path */
3522 osi_Log3(smb_logp, "SMB SEND code %lX as SMB %d: %d", code, class, error);
3525 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3527 osi_Log0(smb_logp,"SendCoreBadOp - NOT_SUPPORTED");
3528 return CM_ERROR_BADOP;
3532 long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3534 unsigned short EchoCount, i;
3535 char *data, *outdata;
3538 EchoCount = (unsigned short) smb_GetSMBParm(inp, 0);
3540 for (i=1; i<=EchoCount; i++) {
3541 data = smb_GetSMBData(inp, &dataSize);
3542 smb_SetSMBParm(outp, 0, i);
3543 smb_SetSMBDataLength(outp, dataSize);
3544 outdata = smb_GetSMBData(outp, NULL);
3545 memcpy(outdata, data, dataSize);
3546 smb_SendPacket(vcp, outp);
3552 /* SMB_COM_READ_RAW */
3553 long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3556 long count, minCount, finalCount;
3560 smb_t *smbp = (smb_t*) inp;
3562 cm_user_t *userp = NULL;
3565 char *rawBuf = NULL;
3570 fd = smb_GetSMBParm(inp, 0);
3571 count = smb_GetSMBParm(inp, 3);
3572 minCount = smb_GetSMBParm(inp, 4);
3573 offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
3575 if (*inp->wctp == 10) {
3576 /* we were sent a request with 64-bit file offsets */
3577 #ifdef AFS_LARGEFILES
3578 offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
3580 if (LargeIntegerLessThanZero(offset)) {
3581 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
3585 if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
3586 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset. Dropping request.");
3589 offset.HighPart = 0;
3593 /* we were sent a request with 32-bit file offsets */
3594 offset.HighPart = 0;
3597 osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
3598 fd, offset.HighPart, offset.LowPart, count);
3600 fidp = smb_FindFID(vcp, fd, 0);
3602 osi_Log2(smb_logp, "smb_ReceiveCoreReadRaw Unknown SMB Fid vcp 0x%p fid %d",
3606 lock_ObtainMutex(&fidp->mx);
3608 lock_ReleaseMutex(&fidp->mx);
3609 smb_ReleaseFID(fidp);
3610 return CM_ERROR_BADFD;
3613 if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
3614 lock_ReleaseMutex(&fidp->mx);
3615 smb_CloseFID(vcp, fidp, NULL, 0);
3616 code = CM_ERROR_NOSUCHFILE;
3622 LARGE_INTEGER LOffset, LLength;
3625 key = cm_GenerateKey(vcp->vcID, pid, fd);
3627 LOffset.HighPart = offset.HighPart;
3628 LOffset.LowPart = offset.LowPart;
3629 LLength.HighPart = 0;
3630 LLength.LowPart = count;
3632 lock_ObtainWrite(&fidp->scp->rw);
3633 code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
3634 lock_ReleaseWrite(&fidp->scp->rw);
3637 lock_ReleaseMutex(&fidp->mx);
3641 lock_ObtainMutex(&smb_RawBufLock);
3643 /* Get a raw buf, from head of list */
3644 rawBuf = smb_RawBufs;
3645 smb_RawBufs = *(char **)smb_RawBufs;
3647 lock_ReleaseMutex(&smb_RawBufLock);
3649 lock_ReleaseMutex(&fidp->mx);
3653 if (fidp->flags & SMB_FID_IOCTL)
3655 rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
3657 /* Give back raw buffer */
3658 lock_ObtainMutex(&smb_RawBufLock);
3659 *((char **) rawBuf) = smb_RawBufs;
3661 smb_RawBufs = rawBuf;
3662 lock_ReleaseMutex(&smb_RawBufLock);
3665 lock_ReleaseMutex(&fidp->mx);
3666 smb_ReleaseFID(fidp);
3669 lock_ReleaseMutex(&fidp->mx);
3671 userp = smb_GetUserFromVCP(vcp, inp);
3673 code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
3679 cm_ReleaseUser(userp);
3682 smb_ReleaseFID(fidp);
3686 memset((char *)ncbp, 0, sizeof(NCB));
3688 ncbp->ncb_length = (unsigned short) finalCount;
3689 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
3690 ncbp->ncb_lana_num = vcp->lana;
3691 ncbp->ncb_command = NCBSEND;
3692 ncbp->ncb_buffer = rawBuf;
3694 code = Netbios(ncbp);
3696 osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
3699 /* Give back raw buffer */
3700 lock_ObtainMutex(&smb_RawBufLock);
3701 *((char **) rawBuf) = smb_RawBufs;
3703 smb_RawBufs = rawBuf;
3704 lock_ReleaseMutex(&smb_RawBufLock);
3710 long smb_ReceiveCoreLockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3712 osi_Log1(smb_logp, "SMB receive core lock record (not implemented); %d + 1 ongoing ops",
3717 long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3719 osi_Log1(smb_logp, "SMB receive core unlock record (not implemented); %d + 1 ongoing ops",