diff --git a/src/WINNT/afsd/cm_daemon.c b/src/WINNT/afsd/cm_daemon.c index 8089847eaa..d80e3ccc0a 100644 --- a/src/WINNT/afsd/cm_daemon.c +++ b/src/WINNT/afsd/cm_daemon.c @@ -49,6 +49,8 @@ static int daemon_ShutdownFlag = 0; #ifndef DJGPP void cm_IpAddrDaemon(long parm) { + extern void smb_CheckVCs(void); + rx_StartClientThread(); while (daemon_ShutdownFlag == 0) { @@ -57,7 +59,8 @@ void cm_IpAddrDaemon(long parm) osi_Log0(afsd_logp, "cm_IpAddrDaemon CheckDownServers"); Sleep(2500); cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); - } + smb_CheckVCs(); + } } } #endif diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 2139fd8d9b..b8f6d79485 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -41,11 +41,6 @@ BOOL isWindows2000 = FALSE; smb_vc_t *dead_vcp = NULL; smb_vc_t *active_vcp = NULL; -/* TODO; logout mechanism needs to be thread-safe */ -char *loggedOutName = NULL; -smb_user_t *loggedOutUserp = NULL; -time_t loggedOutTime; -int loggedOut = 0; int smbShutdownFlag = 0; int smb_LogoffTokenTransfer; @@ -94,20 +89,20 @@ HANDLE smb_lsaHandle; ULONG smb_lsaSecPackage; LSA_STRING smb_lsaLogonOrigin; -#define NCBmax MAXIMUM_WAIT_OBJECTS -EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax]; +#define NCB_MAX MAXIMUM_WAIT_OBJECTS +EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX]; EVENT_HANDLE **NCBreturns; EVENT_HANDLE **NCBShutdown; EVENT_HANDLE *smb_ServerShutdown; -DWORD NCBsessions[NCBmax]; -NCB *NCBs[NCBmax]; -struct smb_packet *bufs[NCBmax]; +DWORD NCBsessions[NCB_MAX]; +NCB *NCBs[NCB_MAX]; +struct smb_packet *bufs[NCB_MAX]; -#define Sessionmax MAXIMUM_WAIT_OBJECTS - 4 -EVENT_HANDLE SessionEvents[Sessionmax]; -unsigned short LSNs[Sessionmax]; -int lanas[Sessionmax]; -BOOL dead_sessions[Sessionmax]; +#define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4 +EVENT_HANDLE SessionEvents[SESSION_MAX]; +unsigned short LSNs[SESSION_MAX]; +int lanas[SESSION_MAX]; +BOOL dead_sessions[SESSION_MAX]; LANA_ENUM lana_list; /* for raw I/O */ @@ -172,6 +167,7 @@ afs_uint32 smb_NowTZ; char *smb_localNamep = NULL; smb_vc_t *smb_allVCsp; +smb_vc_t *smb_deadVCsp; smb_username_t *usernamesp = NULL; @@ -179,7 +175,7 @@ smb_waitingLockRequest_t *smb_allWaitingLocks; /* forward decl */ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, - NCB *ncbp, raw_write_cont_t *rwcp); + NCB *ncbp, raw_write_cont_t *rwcp); void smb_NetbiosInit(); #ifdef DJGPP #ifndef AFS_WIN95_ENV @@ -942,7 +938,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp); - lock_ObtainRead(&smb_rctLock); + lock_ObtainWrite(&smb_rctLock); for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) { fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q); @@ -968,7 +964,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) tid = tidpIter->tid; osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter); - lock_ReleaseRead(&smb_rctLock); + lock_ReleaseWrite(&smb_rctLock); tidp = smb_FindTID(vcp, tid, 0); osi_assert(tidp); @@ -979,7 +975,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) smb_ReleaseTID(tidp); - lock_ObtainRead(&smb_rctLock); + lock_ObtainWrite(&smb_rctLock); } for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) { @@ -990,7 +986,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) uid = uidpIter->userID; osi_Log2(smb_logp, " Cleanup UID %d (uidp=0x%x)", uid, uidpIter); - lock_ReleaseRead(&smb_rctLock); + lock_ReleaseWrite(&smb_rctLock); uidp = smb_FindUID(vcp, uid, 0); osi_assert(uidp); @@ -1001,7 +997,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) smb_ReleaseUID(uidp); - lock_ObtainRead(&smb_rctLock); + lock_ObtainWrite(&smb_rctLock); } /* remove VCP from smb_allVCsp */ @@ -1012,8 +1008,8 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) break; } } - lock_ReleaseRead(&smb_rctLock); - osi_Log0(smb_logp, "Done cleaning up dead vcp"); + lock_ReleaseWrite(&smb_rctLock); + osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp); } smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags) @@ -1063,7 +1059,7 @@ void smb_ReleaseTID(smb_tid_t *tidp) userp = tidp->userp; /* remember to drop ref later */ tidp->userp = NULL; smb_ReleaseVCNoLock(tidp->vcp); - tidp->vcp = 0; + tidp->vcp = NULL; } lock_ReleaseWrite(&smb_rctLock); if (userp) @@ -1122,7 +1118,7 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags) usernamesp = unp; lock_InitializeMutex(&unp->mx, "username_t mutex"); if (flags & SMB_FLAG_AFSLOGON) - unp->flags = SMB_USERFLAG_AFSLOGON; + unp->flags = SMB_USERNAMEFLAG_AFSLOGON; } lock_ReleaseWrite(&smb_rctLock); @@ -1153,10 +1149,12 @@ void smb_ReleaseUsername(smb_username_t *unp) smb_username_t *up; smb_username_t **lupp; cm_user_t *userp = NULL; + time_t now = osi_Time(); lock_ObtainWrite(&smb_rctLock); osi_assert(unp->refCount-- > 0); - if (unp->refCount == 0 && !(unp->flags & SMB_USERFLAG_AFSLOGON)) { + if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) && + !((unp->flags & SMB_USERNAMEFLAG_LOGOFF) && smb_LogoffTokenTransfer)) { lupp = &usernamesp; for(up = *lupp; up; lupp = &up->nextp, up = *lupp) { if (up == unp) @@ -1164,6 +1162,7 @@ void smb_ReleaseUsername(smb_username_t *unp) } osi_assert(up != NULL); *lupp = up->nextp; + up->nextp = NULL; /* do not remove this */ lock_FinalizeMutex(&unp->mx); userp = unp->userp; free(unp->name); @@ -1196,6 +1195,7 @@ void smb_ReleaseUID(smb_user_t *uidp) lock_FinalizeMutex(&uidp->mx); unp = uidp->unp; smb_ReleaseVCNoLock(uidp->vcp); + uidp->vcp = NULL; free(uidp); } lock_ReleaseWrite(&smb_rctLock); @@ -1353,16 +1353,14 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) void smb_ReleaseFID(smb_fid_t *fidp) { - cm_scache_t *scp; - cm_user_t *userp; + cm_scache_t *scp = NULL; + cm_user_t *userp = NULL; smb_vc_t *vcp = NULL; smb_ioctl_t *ioctlp; if (!fidp) return; - scp = NULL; - userp = NULL; lock_ObtainWrite(&smb_rctLock); osi_assert(fidp->refCount-- > 0); if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) { @@ -1390,7 +1388,8 @@ void smb_ReleaseFID(smb_fid_t *fidp) free(fidp); - smb_ReleaseVCNoLock(vcp); + if (vcp) + smb_ReleaseVCNoLock(vcp); } lock_ReleaseWrite(&smb_rctLock); @@ -2455,6 +2454,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp) } dead_vcp = vcp; vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + dead_sessions[vcp->session] = TRUE; } if (localNCB) @@ -3007,27 +3007,6 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops", ongoingOps - 1); - if (!isGateway) { - if (active_vcp) { - DWORD now = GetTickCount(); - if (now - last_msg_time >= 30000) { - smb_vc_t *avcp = active_vcp; - active_vcp = NULL; - osi_Log1(smb_logp,"Setting dead_vcp %x", avcp); - if (dead_vcp) { - osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); - smb_CleanupDeadVC(dead_vcp); - smb_ReleaseVC(dead_vcp); - } - smb_HoldVC(avcp); - dead_vcp = avcp; - dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD; - smb_ReleaseVC(avcp); - } - } - } - - inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK; namep = smb_GetSMBData(inp, &dbytes); namex = 0; @@ -3218,9 +3197,41 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } +void smb_CheckVCs(void) +{ + smb_vc_t * vcp; + smb_packet_t * outp = GetPacket(); + smb_t *smbp; + + for ( vcp=smb_allVCsp; vcp; vcp = vcp->nextp ) + { + if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) + continue; + + smb_FormatResponsePacket(vcp, NULL, outp); + smbp = (smb_t *)outp; + outp->inCom = smbp->com = 0x2b /* Echo */; + smbp->tid = 0xFFFF; + smbp->pid = 0; + smbp->uid = 0; + smbp->mid = 0; + smbp->res[0] = 0; + smbp->res[1] = 0; + + smb_SetSMBParm(outp, 0, 0); + smb_SetSMBDataLength(outp, 0); + + smb_SendPacket(vcp, outp); + } + + smb_FreePacket(outp); +} + void smb_Daemon(void *parmp) { afs_uint32 count = 0; + smb_username_t **unpp; + time_t now; while(smbShutdownFlag == 0) { count++; @@ -3250,7 +3261,54 @@ void smb_Daemon(void *parmp) if ( smb_localZero != old_localZero ) cm_noteLocalMountPointChange(); #endif - } + + smb_CheckVCs(); + } + + /* XXX GC the smb_username_t objects with refCount 0 and + * neither SMB_USERNAMEFLAG_AFSLOGON nor (SMB_USERNAMEFLAG_LOGOFF + * && smb_LogoffTokenTransfer && + * now > last_logoff_t + smb_LogoffTransferTimeout) + */ + now = osi_Time(); + lock_ObtainWrite(&smb_rctLock); + for ( unpp=&usernamesp; *unpp; ) { + int delete = 0; + smb_username_t *unp; + + lock_ObtainMutex(&(*unpp)->mx); + if ( (*unpp)->refCount > 0 ) + ; + else if ((*unpp)->flags & SMB_USERNAMEFLAG_AFSLOGON) + ; + else if (!(((*unpp)->flags & SMB_USERNAMEFLAG_LOGOFF) && smb_LogoffTokenTransfer)) + delete = 1; + else if ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now) + delete = 1; + lock_ReleaseMutex(&(*unpp)->mx); + + if (delete) { + cm_user_t * userp; + + unp = *unpp; + *unpp = unp->nextp; + unp->nextp = NULL; + lock_FinalizeMutex(&unp->mx); + userp = unp->userp; + free(unp->name); + free(unp->machine); + free(unp); + if (userp) { + lock_ReleaseWrite(&smb_rctLock); + cm_ReleaseUser(userp); + lock_ObtainWrite(&smb_rctLock); + } + } else { + unpp = &(*unpp)->nextp; + } + } + lock_ReleaseWrite(&smb_rctLock); + /* XXX GC dir search entries */ } } @@ -6990,8 +7048,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, if (inp->inCom == 0x1d) /* Raw Write */ - code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, - rwcp); + code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp); else { osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp 0x%x lana %d lsn %d",(int)vcp,vcp->lana,vcp->lsn); osi_Log4(smb_logp,"Dispatch %s vcp 0x%x lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn); @@ -7163,18 +7220,6 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, outWctp = tp; } /* while loop over all requests in the packet */ - /* done logging out, turn off logging-out flag */ - if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) { - vcp->justLoggedOut = NULL; - if (loggedOut) { - loggedOut = 0; - free(loggedOutName); - loggedOutName = NULL; - smb_ReleaseUID(loggedOutUserp); - loggedOutUserp = NULL; - } - } - /* now send the output packet, and return */ if (!noSend) smb_SendPacket(vcp, outp); @@ -7407,6 +7452,10 @@ void smb_Server(VOID *parmp) outbufp->ncbp = outncbp; while (1) { + if (vcp) { + smb_ReleaseVC(vcp); + vcp = NULL; + } code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx], FALSE, INFINITE); @@ -7580,6 +7629,7 @@ void smb_Server(VOID *parmp) switch (rc) { case NRC_GOODRET: + vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]); break; case NRC_PENDING: @@ -7592,8 +7642,6 @@ void smb_Server(VOID *parmp) case NRC_SCLOSED: /* Client closed session */ dead_sessions[idx_session] = TRUE; - if (vcp) - smb_ReleaseVC(vcp); vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]); if (vcp) { if (dead_vcp == vcp) @@ -7601,24 +7649,14 @@ void smb_Server(VOID *parmp) else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x", vcp, vcp->usersp); - smb_HoldVC(vcp); if (dead_vcp) { osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); smb_CleanupDeadVC(dead_vcp); smb_ReleaseVC(dead_vcp); } - dead_vcp = vcp; vcp->flags |= SMB_VCFLAG_ALREADYDEAD; - } - - if (vcp->justLoggedOut) { - loggedOut = 1; - loggedOutTime = vcp->logoffTime; - loggedOutName = strdup(vcp->justLoggedOut->unp->name); - loggedOutUserp = vcp->justLoggedOut; - lock_ObtainWrite(&smb_rctLock); - loggedOutUserp->refCount++; - lock_ReleaseWrite(&smb_rctLock); + dead_vcp = vcp; + vcp = NULL; } } goto doneWithNCB; @@ -7654,15 +7692,31 @@ void smb_Server(VOID *parmp) * continue; */ + vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]); break; } default: - /* A weird error code. Log it, sleep, and - * continue. */ + /* A weird error code. Log it, sleep, and continue. */ + vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]); if (vcp && vcp->errorCount++ > 3) { osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount); dead_sessions[idx_session] = TRUE; + if (dead_vcp == vcp) + osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp); + else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { + osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x", + vcp, vcp->usersp); + if (dead_vcp) { + osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); + smb_CleanupDeadVC(dead_vcp); + smb_ReleaseVC(dead_vcp); + } + vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + dead_vcp = vcp; + vcp = NULL; + } + goto doneWithNCB; } else { thrd_Sleep(1000); @@ -7677,9 +7731,6 @@ void smb_Server(VOID *parmp) if (smb_concurrentCalls > smb_maxObsConcurrentCalls) smb_maxObsConcurrentCalls = smb_concurrentCalls; - if (vcp) - smb_ReleaseVC(vcp); - vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num); /* * If at this point vcp is NULL (implies that packet was invalid) * then we are in big trouble. This means either : @@ -7732,7 +7783,6 @@ void smb_Server(VOID *parmp) continue; } - vcp->errorCount = 0; bufp = (struct smb_packet *) ncbp->ncb_buffer; #ifdef DJGPP @@ -7879,8 +7929,9 @@ void smb_Listener(void *parmp) NCB *ncbp; long code = 0; long len; - long i, j; - smb_vc_t *vcp = 0; + long i; + int session, thread; + smb_vc_t *vcp = NULL; int flags = 0; char rname[NCBNAMSZ+1]; char cname[MAX_COMPUTERNAME_LENGTH+1]; @@ -7980,62 +8031,97 @@ void smb_Listener(void *parmp) if (strncmp(rname, cname, NCBNAMSZ) != 0) flags |= SMB_VCFLAG_REMOTECONN; - osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn); /* lock */ lock_ObtainMutex(&smb_ListenerLock); - /* New generation */ - sessionGen++; + osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname)); + osi_Log1(smb_logp, "SMB session startup, %d ongoing ops", ongoingOps); + + /* now ncbp->ncb_lsn is the connection ID */ + vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num); + if (vcp->session == 0) { + /* New generation */ + osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn); + sessionGen++; - /* Log session startup */ + /* Log session startup */ #ifdef NOTSERVICE - fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host " - "%s\n", - ncbp->ncb_lsn,ncbp->ncb_lana_num, rname); + fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n", + ncbp->ncb_lsn,ncbp->ncb_lana_num, rname); #endif /* NOTSERVICE */ - osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops", - ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps); + osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops", + ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps); - if (reportSessionStartups) { + if (reportSessionStartups) { #ifndef DJGPP - HANDLE h; - char *ptbuf[1]; - char s[100]; + HANDLE h; + char *ptbuf[1]; + char s[100]; - h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); - sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps); - ptbuf[0] = s; - ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL, - 1, 0, ptbuf, NULL); - DeregisterEventSource(h); + h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); + sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps); + ptbuf[0] = s; + ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL, + 1, 0, ptbuf, NULL); + DeregisterEventSource(h); #else /* DJGPP */ - time(&now); - fprintf(stderr, "%s: New session %d starting from host %s\n", - asctime(localtime(&now)), ncbp->ncb_lsn, rname); - fflush(stderr); + time(&now); + fprintf(stderr, "%s: New session %d starting from host %s\n", + asctime(localtime(&now)), ncbp->ncb_lsn, rname); + fflush(stderr); #endif /* !DJGPP */ - } - osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname)); - osi_Log1(smb_logp, "SMB session startup, %d ongoing ops", - ongoingOps); + } - /* now ncbp->ncb_lsn is the connection ID */ - vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num); - vcp->flags |= flags; - strcpy(vcp->rname, rname); + strcpy(vcp->rname, rname); + vcp->flags |= flags; - /* Allocate slot in session arrays */ - /* Re-use dead session if possible, otherwise add one more */ - /* But don't look at session[0], it is reserved */ - for (i = 1; i < numSessions; i++) { - if (dead_sessions[i]) { - osi_Log1(smb_logp, "connecting to dead session [ %d ]", i); - dead_sessions[i] = FALSE; - break; - } - } + /* Allocate slot in session arrays */ + /* Re-use dead session if possible, otherwise add one more */ + /* But don't look at session[0], it is reserved */ + for (session = 1; session < numSessions; session++) { + if (dead_sessions[session]) { + osi_Log1(smb_logp, "connecting to dead session [ %d ]", session); + dead_sessions[session] = FALSE; + break; + } + } + } else { + /* We are re-using an existing VC because the lsn and lana + * were re-used */ + session = vcp->session; + + osi_Log1(smb_logp, "Re-using session lsn %d", ncbp->ncb_lsn); + + /* Log session startup */ +#ifdef NOTSERVICE + fprintf(stderr, "Re-using session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n", + ncbp->ncb_lsn,ncbp->ncb_lana_num, rname); +#endif /* NOTSERVICE */ + osi_Log4(smb_logp, "Re-using session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops", + ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps); - if (i >= Sessionmax - 1 || numNCBs >= NCBmax - 1) { + if (reportSessionStartups) { +#ifndef DJGPP + HANDLE h; + char *ptbuf[1]; + char s[100]; + + h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); + sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps); + ptbuf[0] = s; + ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL, + 1, 0, ptbuf, NULL); + DeregisterEventSource(h); +#else /* DJGPP */ + time(&now); + fprintf(stderr, "%s: Re-using session %d starting from host %s\n", + asctime(localtime(&now)), ncbp->ncb_lsn, rname); + fflush(stderr); +#endif /* !DJGPP */ + } + } + + if (i >= SESSION_MAX - 1 || numNCBs >= NCB_MAX - 1) { unsigned long code = CM_ERROR_ALLBUSY; smb_packet_t * outp = GetPacket(); unsigned char *outWctp; @@ -8071,18 +8157,23 @@ void smb_Listener(void *parmp) } smb_SendPacket(vcp, outp); smb_FreePacket(outp); + + vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + smb_CleanupDeadVC(vcp); + smb_ReleaseVC(vcp); } else { /* assert that we do not exceed the maximum number of sessions or NCBs. - * we should probably want to wait for a session to be freed in case - * we run out. - */ - osi_assert(i < Sessionmax - 1); - osi_assert(numNCBs < NCBmax - 1); /* if we pass this test we can allocate one more */ + * we should probably want to wait for a session to be freed in case + * we run out. + */ + osi_assert(session < SESSION_MAX - 1); + osi_assert(numNCBs < NCB_MAX - 1); /* if we pass this test we can allocate one more */ - LSNs[i] = ncbp->ncb_lsn; - lanas[i] = ncbp->ncb_lana_num; + vcp->session = session; + LSNs[session] = ncbp->ncb_lsn; + lanas[session] = ncbp->ncb_lana_num; - if (i == numSessions) { + if (session == numSessions) { /* Add new NCB for new session */ char eventName[MAX_PATH]; @@ -8092,18 +8183,18 @@ void smb_Listener(void *parmp) numNCBs++; thrd_SetEvent(NCBavails[0]); thrd_SetEvent(NCBevents[0]); - for (j = 0; j < smb_NumServerThreads; j++) - thrd_SetEvent(NCBreturns[j][0]); + for (thread = 0; thread < smb_NumServerThreads; thread++) + thrd_SetEvent(NCBreturns[thread][0]); /* Also add new session event */ - sprintf(eventName, "SessionEvents[%d]", i); - SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName); + sprintf(eventName, "SessionEvents[%d]", session); + SessionEvents[session] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName); if ( GetLastError() == ERROR_ALREADY_EXISTS ) osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName)); numSessions++; osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions); thrd_SetEvent(SessionEvents[0]); } else { - thrd_SetEvent(SessionEvents[i]); + thrd_SetEvent(SessionEvents[session]); } } @@ -8417,7 +8508,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, if ( GetLastError() == ERROR_ALREADY_EXISTS ) afsi_log("Event Object Already Exists: %s", eventName); for (i = 0; i < smb_NumServerThreads; i++) { - NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE)); + NCBreturns[i] = malloc(NCB_MAX * sizeof(EVENT_HANDLE)); NCBreturns[i][0] = retHandle; } diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 4f024521da..4ae634f34a 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -167,9 +167,8 @@ typedef struct smb_packet { } smb_packet_t; /* smb_packet flags */ -#define SMB_PACKETFLAG_PROFILE_UPDATE_OK 1 -#define SMB_PACKETFLAG_NOSEND 2 -#define SMB_PACKETFLAG_SUSPENDED 4 +#define SMB_PACKETFLAG_NOSEND 1 +#define SMB_PACKETFLAG_SUSPENDED 2 /* a structure for making Netbios calls; locked by smb_globalLock */ #define SMB_NCBMAGIC 0x2334344 @@ -204,8 +203,6 @@ typedef struct smb_vc { struct smb_tid *tidsp; /* the first child in the tid list */ struct smb_user *usersp; /* the first child in the user session list */ struct smb_fid *fidsp; /* the first child in the open file list */ - struct smb_user *justLoggedOut; /* ready for profile upload? */ - time_t logoffTime; /* tick count when logged off */ unsigned char errorCount; char rname[17]; int lana; @@ -213,6 +210,7 @@ typedef struct smb_vc { void * secCtx; /* security context when negotiating SMB extended auth * valid when SMB_VCFLAG_AUTH_IN_PROGRESS is set */ + unsigned short session; /* This is the Session Index associated with the NCBs */ } smb_vc_t; /* have we negotiated ... */ @@ -236,6 +234,8 @@ typedef struct smb_user { struct smb_username *unp; /* user name struct */ } smb_user_t; +#define SMB_USERFLAG_DELETE 1 /* delete struct when ref count zero */ + typedef struct smb_username { struct smb_username *nextp; /* next sibling */ unsigned long refCount; /* ref count */ @@ -244,10 +244,25 @@ typedef struct smb_username { struct cm_user *userp; /* CM user structure */ char *name; /* user name */ char *machine; /* machine name */ + time_t last_logoff_t; /* most recent logoff time */ } smb_username_t; -#define SMB_USERFLAG_DELETE 1 /* delete struct when ref count zero */ -#define SMB_USERFLAG_AFSLOGON 2 /* do not delete when the refCount reaches zero */ +/* The SMB_USERNAMEFLAG_AFSLOGON is used to preserve the existence of an + * smb_username_t even when the refCount is zero. This is used to ensure + * that tokens set to a username during the integrated logon process are + * preserved until the SMB Session that will require the tokens is created. + * The cm_IoctlSetTokens() function when executed from the Network Provider + * connects to the AFS Client Service using the credentials of the machine + * and not the user for whom the tokens are being configured. */ +#define SMB_USERNAMEFLAG_AFSLOGON 1 + +/* The SMB_USERNAMEFLAG_LOGOFF is used to indicate that the user most + * recently logged off at 'last_logoff_t'. The smb_username_t should not + * be deleted even if the refCount is zero before 'last_logoff_t' + + * 'smb_LogoffTransferTimeout' if 'smb_LogoffTokenTransfer' is non-zero. + * The smb_Daemon() thread is responsible for purging the expired objects */ + +#define SMB_USERNAMEFLAG_LOGOFF 2 #define SMB_MAX_USERNAME_LENGTH 256 @@ -577,10 +592,6 @@ extern void smb_HoldVCNoLock(smb_vc_t *vcp); /* some globals, too */ extern char *smb_localNamep; -extern int loggedOut; -extern time_t loggedOutTime; -extern char *loggedOutName; -extern smb_user_t *loggedOutUserp; extern osi_log_t *smb_logp; diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 884014a9c7..11618e09b5 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -854,11 +854,11 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * /* do a global search for the username/machine name pair */ unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE); lock_ObtainMutex(&unp->mx); - if (unp->flags & SMB_USERFLAG_AFSLOGON) { + if (unp->flags & SMB_USERNAMEFLAG_AFSLOGON) { /* clear the afslogon flag so that the tickets can now * be freed when the refCount returns to zero. */ - unp->flags &= ~SMB_USERFLAG_AFSLOGON; + unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON; } lock_ReleaseMutex(&unp->mx); @@ -941,27 +941,30 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou /* don't get tokens from this VC */ vcp->flags |= SMB_VCFLAG_ALREADYDEAD; - inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK; - /* find the tree and free it */ uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); if (uidp) { - char *s1 = NULL, *s2 = NULL; + smb_username_t * unp; - if (s2 == NULL) s2 = " "; - if (s1 == NULL) {s1 = s2; s2 = " ";} - - osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID, - osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), - osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2)); + osi_Log2(smb_logp, "SMB3 user logoffX uid %d name %s", uidp->userID, + osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " ")); lock_ObtainMutex(&uidp->mx); uidp->flags |= SMB_USERFLAG_DELETE; - /* + /* * it doesn't get deleted right away * because the vcp points to it */ + unp = uidp->unp; lock_ReleaseMutex(&uidp->mx); + + if (unp && smb_LogoffTokenTransfer) { + lock_ObtainMutex(&unp->mx); + unp->flags |= SMB_USERNAMEFLAG_LOGOFF; + unp->last_logoff_t = osi_Time() + smb_LogoffTransferTimeout; + lock_ReleaseMutex(&unp->mx); + } + smb_ReleaseUID(uidp); } else @@ -1175,8 +1178,10 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp, /* free a tran2 packet; must be called with smb_globalLock held */ void smb_FreeTran2Packet(smb_tran2Packet_t *t2p) { - if (t2p->vcp) + if (t2p->vcp) { smb_ReleaseVC(t2p->vcp); + t2p->vcp = NULL; + } if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) { if (t2p->parmsp) free(t2p->parmsp);