]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-smb-dont-crash-vista-20061128
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 28 Nov 2006 09:17:14 +0000 (09:17 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 28 Nov 2006 09:17:14 +0000 (09:17 +0000)
Unlike previous versions of the OS, Vista performs a shutdown on
the Microsoft Loopback adapter just like it would on a real adapter.
This causes the smb_Listener threads to trigger a panic during a
suspend/hibernate power event.

The fix is to unbind from the network adapters in response to a
suspend/hibernate power event and then rebind to the adapters
when a resume power event is received.  Note that the resume events
are not reliably delivered so it is possible the afs service will
not be accessible.  However, this is the best we can do.

(cherry picked from commit 1ed0460435ec05150526c951d1ff32dd3b5a9c39)

src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h

index d755f5e8cc6d3d1ee24c497fe459bd1739e563f5..09941a4f54058364c0d958c551b01d976fcb31ab 100644 (file)
@@ -232,6 +232,12 @@ afsd_ServiceControlHandlerEx(
     DWORD dummyLen, doTrace;
     long code;
     DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
+    OSVERSIONINFO osVersion;
+
+    /* Get the version of Windows */
+    memset(&osVersion, 0x00, sizeof(osVersion));
+    osVersion.dwOSVersionInfoSize = sizeof(osVersion);
+    GetVersionEx(&osVersion);
 
     switch (ctrlCode) 
     {
@@ -318,23 +324,33 @@ afsd_ServiceControlHandlerEx(
                                                                                                                          
                     /* allow remaining case PBT_WhatEver */                                           
                 case PBT_APMSUSPEND:                         
-                    afsi_log("SERVICE_CONTROL_APMSUSPEND"); 
+                    afsi_log("SERVICE_CONTROL_APMSUSPEND");
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_StopListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMSTANDBY:                  
                     afsi_log("SERVICE_CONTROL_APMSTANDBY"); 
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_StopListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMRESUMECRITICAL:             
                     afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL"); 
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMRESUMESUSPEND:                                                        
                     afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND"); 
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMRESUMESTANDBY:                                                        
                     afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY"); 
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMBATTERYLOW:                                                           
@@ -355,6 +371,8 @@ afsd_ServiceControlHandlerEx(
                     break;                                  
                 case PBT_APMRESUMEAUTOMATIC:                                                      
                     afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC"); 
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners();
                     dwRet = NO_ERROR;                       
                     break;                                  
                 default:                                                                          
index ee5755956f33e9cd921ea7cd70e8904c80abb3db..29eea5ccc7a0b54f564567e5de239075a13efadd 100644 (file)
@@ -36,7 +36,8 @@
 /* These characters are illegal in Windows filenames */
 static char *illegalChars = "\\/:*?\"<>|";
 
-int smbShutdownFlag = 0;
+static int smbShutdownFlag = 0;
+static int smb_ListenerState = SMB_LISTENER_STOPPED;
 
 int smb_LogoffTokenTransfer;
 time_t smb_LogoffTransferTimeout;
@@ -8255,7 +8256,7 @@ void smb_Listener(void *parmp)
     GetComputerName(cname, &cnamelen);
     _strupr(cname);
 
-    while (1) {
+    while (smb_ListenerState == SMB_LISTENER_STARTED) {
         memset(ncbp, 0, sizeof(NCB));
         flags = 0;
 
@@ -8278,15 +8279,34 @@ void smb_Listener(void *parmp)
 #else /* DJGPP */
         code = Netbios(ncbp, dos_ncb);
 #endif
+       if (code == NRC_BRIDGE) {
+            if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
+#ifndef DJGPP
+                ExitThread(1);
+#else
+                thrd_Exit(1);
+#endif
+            }
+
+           osi_Log2(smb_logp,
+                     "NCBLISTEN lana=%d failed with NRC_BRIDGE.  Listener thread exiting.",
+                     ncbp->ncb_lana_num, code);
 
-        if (code != 0)
+           for (i = 0; i < lana_list.length; i++) {
+               if (lana_list.lana[i] == ncbp->ncb_lana_num) {
+                   lana_list.lana[i] = 255;
+                   break;
+               }
+           }
+           return;
+       } else if (code != 0)
         {
 #ifndef DJGPP
             char tbuffer[256];
 #endif
 
             /* terminate silently if shutdown flag is set */
-            if (smbShutdownFlag == 1) {
+            if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
 #ifndef DJGPP
                 ExitThread(1);
 #else
@@ -8510,6 +8530,8 @@ void smb_Listener(void *parmp)
         /* unlock */
         lock_ReleaseMutex(&smb_ListenerLock);
     }  /* dispatch while loop */
+
+    FreeNCB(ncbp);
 }
 
 /* initialize Netbios */
@@ -8524,12 +8546,6 @@ void smb_NetbiosInit()
     int delname_tried=0;
     int len;
     int lana_found = 0;
-    OSVERSIONINFO Version;
-
-    /* Get the version of Windows */
-    memset(&Version, 0x00, sizeof(Version));
-    Version.dwOSVersionInfoSize = sizeof(Version);
-    GetVersionEx(&Version);
 
     /* setup the NCB system */
     ncbp = GetNCB();
@@ -8614,7 +8630,9 @@ void smb_NetbiosInit()
             afsi_log("Netbios NCBADDNAME added new name >%s<",name);
         }
 
-        if (code == 0) code = ncbp->ncb_retcode;
+        if (code == 0) 
+           code = ncbp->ncb_retcode;
+
         if (code == 0) {
             afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
 #ifdef DJGPP
@@ -8679,6 +8697,91 @@ void smb_NetbiosInit()
     FreeNCB(ncbp);
 }
 
+void smb_StartListeners()
+{
+    int i;
+    int lpid;
+    thread_t phandle;
+
+    if (smb_ListenerState == SMB_LISTENER_STARTED)
+       return;
+    
+    smb_ListenerState = SMB_LISTENER_STARTED;
+
+    for (i = 0; i < lana_list.length; i++) {
+        if (lana_list.lana[i] == 255) 
+            continue;
+        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
+                               (void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
+        osi_assert(phandle != NULL);
+        thrd_CloseHandle(phandle);
+    }
+}
+
+void smb_RestartListeners()
+{
+    if (smb_ListenerState == SMB_LISTENER_STARTED)
+       return;
+
+    smb_NetbiosInit();
+    smb_StartListeners();
+}
+
+void smb_StopListeners()
+{
+    NCB *ncbp;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+#endif /* DJGPP */
+    int lana, code, l;
+
+    if (smb_ListenerState == SMB_LISTENER_STOPPED)
+       return;
+
+    smb_ListenerState = SMB_LISTENER_STOPPED;
+
+    ncbp = GetNCB();
+
+    /* Unregister the SMB name */
+    for (l = 0; l < lana_list.length; l++) {
+        lana = lana_list.lana[l];
+
+       memset(ncbp, 0, sizeof(*ncbp));
+        ncbp->ncb_command = NCBDELNAME;
+        ncbp->ncb_lana_num = lana;
+        memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else /* DJGPP */
+        code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+          
+        afsi_log("Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
+                 lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
+
+       /* and then reset the LANA; this will cause the listener threads to exit */
+        ncbp->ncb_command = NCBRESET;
+        ncbp->ncb_callname[0] = 100;
+        ncbp->ncb_callname[2] = 100;
+        ncbp->ncb_lana_num = lana_list.lana[l];
+        code = Netbios(ncbp);
+        if (code == 0) 
+            code = ncbp->ncb_retcode;
+        if (code != 0) {
+            afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[l], code);
+        } else {
+            afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[l]);
+        }
+
+       /* mark the adapter invalid */
+       lana_list.lana[l] = 255;  /* invalid lana */
+    }
+
+    lana_list.length = 0;
+    FreeNCB(ncbp);
+    Sleep(1000);       /* give the listener threads a chance to exit */
+}
+
 void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
               int nThreads
 #ifndef DJGPP
@@ -8969,6 +9072,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                  * performance by removing the network access and works around a bug
                  * seen at sites which are using a MIT Kerberos principal to login
                  * to machines joined to a non-root domain in a multi-domain forest.
+                * MsV1_0SetProcessOption was added in Windows XP.
                  */
                 PVOID pResponse = NULL;
                 ULONG cbResponse = 0;
@@ -9059,14 +9163,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 
     /* Start listeners, waiters, servers, and daemons */
 
-    for (i = 0; i < lana_list.length; i++) {
-        if (lana_list.lana[i] == 255) 
-            continue;
-        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
-                               (void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
-        osi_assert(phandle != NULL);
-        thrd_CloseHandle(phandle);
-    }
+    smb_StartListeners();
 
 #ifndef DJGPP
     phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
@@ -9231,7 +9328,7 @@ void smb_Shutdown(void)
         }
     }
     lock_ReleaseWrite(&smb_rctLock);
-
+    FreeNCB(ncbp);
     TlsFree(smb_TlsRequestSlot);
 }
 
index e765eaf8422592573c100e06f7134ebf7f4435b7..aa381020b8a4cdeb46efca1d416bb325e84e7e98 100644 (file)
@@ -746,6 +746,11 @@ extern DWORD smb_ServerExceptionFilter(void);
 extern void smb_UpdateServerPriority(void);
 extern void smb_SetRequestStartTime(void);
 extern void smb_ResetServerPriority(void);
+extern void smb_RestartListeners(void);
+extern void smb_StopListeners(void);
+
+#define SMB_LISTENER_STOPPED 0
+#define SMB_LISTENER_STARTED 1
 
 /* include other include files */
 #include "smb3.h"