r11909: Implement 'reset on zero vc'. This kills other connections when a session
authorVolker Lendecke <vlendec@samba.org>
Fri, 25 Nov 2005 12:31:40 +0000 (12:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:34 +0000 (11:05 -0500)
setup comes in with the vc (virtual connection) field set to zero. This is
done by Windows, probably you can tweak that by some registry key.

This boolean option controls whether an incoming session setup
should kill other connections coming from the same IP. This matches
        the default Windows 2003 behaviour.

Setting this parameter to yes becomes necessary when you have a flaky
network and windows decides to reconnect while the old connection
still has files with share modes open. These files become inaccessible
over the new connection.

The client sends a zero VC on the new connection, and Windows 2003
kills all other connections coming from the same IP. This way the
locked files are accessible again.

Please be aware that enabling this option will kill connections behind
a masquerading router.

Volker
(This used to be commit 5629ca16235f0aa21fea3afd9e414309e4e1374e)

source3/param/loadparm.c
source3/smbd/session.c
source3/smbd/sesssetup.c

index f45d8cf9527549a775cbc10d909d4dc634312a3d..86a5353dca7d62cf5a5c5fe3d2ebfaf643dc7f5a 100644 (file)
@@ -301,6 +301,7 @@ typedef struct
        int name_cache_timeout;
        int client_signing;
        int server_signing;
+       BOOL bResetOnZeroVC;
        param_opt_struct *param_opt;
 }
 global;
@@ -951,6 +952,7 @@ static struct parm_struct parm_table[] = {
        {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, 
        {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, 
        {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
+       {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED}, 
 
        {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility,  NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
@@ -1522,6 +1524,7 @@ static void init_globals(void)
        Globals.bUseMmap = True;
 #endif
        Globals.bUnixExtensions = True;
+       Globals.bResetOnZeroVC = False;
 
        /* hostname lookups can be very expensive and are broken on
           a large number of sites (tridge) */
@@ -1809,6 +1812,7 @@ FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
 
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
+FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
index 9a9a0d90b24a3a003445e34121cd456fafce41fd..27f760a088e045f5f21372084a676cd2007bb930 100644 (file)
@@ -198,7 +198,8 @@ void session_yield(user_struct *vuser)
        tdb_delete(tdb, key);
 }
 
-static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state)
+BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
+                     void *state)
 {
        if (!session_init()) {
                DEBUG(3, ("No tdb opened\n"));
index 8aa046b85a66a6ca1d255fcdd4850fe433a8cad1..a22a575c762ccabe3127db4cd45cd8c0b4490df5 100644 (file)
@@ -744,6 +744,29 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
  a new session setup with VC==0 is ignored.
 ****************************************************************************/
 
+static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+                               void *p)
+{
+       struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
+       const char *ip = (const char *)p;
+
+       if (!process_exists(pid_to_procid(sessionid->pid))) {
+               return 0;
+       }
+
+       if (sessionid->pid == sys_getpid()) {
+               return 0;
+       }
+
+       if (strcmp(ip, sessionid->ip_addr) != 0) {
+               return 0;
+       }
+
+       message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
+                        NULL, 0, True);
+       return 0;
+}
+
 static void setup_new_vc_session(void)
 {
        DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
@@ -751,6 +774,9 @@ static void setup_new_vc_session(void)
        conn_close_all();
        invalidate_all_vuids();
 #endif
+       if (lp_reset_on_zero_vc()) {
+               session_traverse(shutdown_other_smbds, client_addr());
+       }
 }
 
 /****************************************************************************