s3: Allow disabling of mdns registrations
[kai/samba.git] / source3 / param / loadparm.c
index ba7c212f7f26d4d25473720997238be89ceb4fb8..f65682fbedf43544399f82ff5a6b75613fd5f316 100644 (file)
    Copyright (C) Stefan (metze) Metzmacher 2002
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
    Copyright (C) Michael Adam 2008
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "printing.h"
+#include "lib/smbconf/smbconf.h"
+#include "lib/smbconf/smbconf_init.h"
+#include "lib/smbconf/smbconf_reg.h"
+
+#include "ads.h"
+#include "../librpc/gen_ndr/svcctl.h"
+
+#include "smb_signing.h"
+#include "dbwrap.h"
+#include "smbldap.h"
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
 
 #ifdef HAVE_HTTPCONNECTENCRYPT
 #include <cups/http.h>
@@ -60,7 +74,6 @@
 
 bool bLoaded = False;
 
-extern enum protocol_types Protocol;
 extern userdom_struct current_user_info;
 
 #ifndef GLOBAL_NAME
@@ -105,6 +118,7 @@ struct param_opt_struct {
        char *key;
        char *value;
        char **list;
+       unsigned flags;
 };
 
 /*
@@ -157,6 +171,7 @@ struct global {
        char *szRemoteAnnounce;
        char *szRemoteBrowseSync;
        char *szSocketAddress;
+       bool bNmbdBindExplicitBroadcast;
        char *szNISHomeMapName;
        char *szAnnounceVersion;        /* This is initialised in init_globals */
        char *szWorkgroup;
@@ -177,6 +192,7 @@ struct global {
        char *szShutdownScript;
        char *szAbortShutdownScript;
        char *szUsernameMapScript;
+       int iUsernameMapCacheTime;
        char *szCheckPasswordScript;
        char *szWINSHook;
        char *szUtmpDir;
@@ -199,8 +215,9 @@ struct global {
        bool bWinbindOfflineLogon;
        bool bWinbindNormalizeNames;
        bool bWinbindRpcOnly;
+       bool bCreateKrb5Conf;
        char *szIdmapBackend;
-       char *szIdmapAllocBackend;
+       bool bIdmapReadOnly;
        char *szAddShareCommand;
        char *szChangeShareCommand;
        char *szDeleteShareCommand;
@@ -246,7 +263,7 @@ struct global {
        int oplock_break_wait_time;
        int winbind_cache_time;
        int winbind_reconnect_delay;
-       int winbind_max_idle_children;
+       int winbind_max_clients;
        char **szWinbindNssInfo;
        int iLockSpinTime;
        char *szLdapMachineSuffix;
@@ -255,6 +272,8 @@ struct global {
        char *szLdapGroupSuffix;
        int ldap_ssl;
        bool ldap_ssl_ads;
+       int ldap_deref;
+       int ldap_follow_referral;
        char *szLdapSuffix;
        char *szLdapAdminDn;
        int ldap_debug_level;
@@ -266,6 +285,8 @@ struct global {
        char *ctdbdSocket;
        char **szClusterAddresses;
        bool clustering;
+       int ctdb_timeout;
+       int ctdb_locktime_warn_threshold;
        int ldap_passwd_sync;
        int ldap_replication_sleep;
        int ldap_timeout; /* This is initialised in init_globals */
@@ -345,12 +366,19 @@ struct global {
        int iIdmapCacheTime;
        int iIdmapNegativeCacheTime;
        bool bResetOnZeroVC;
+       bool bLogWriteableFilesOnExit;
        int iKeepalive;
        int iminreceivefile;
        struct param_opt_struct *param_opt;
        int cups_connection_timeout;
        char *szSMBPerfcountModule;
        bool bMapUntrustedToDomain;
+       bool bAsyncSMBEchoHandler;
+       bool bMulticastDnsRegister;
+       int ismb2_max_read;
+       int ismb2_max_write;
+       int ismb2_max_trans;
+       char *ncalrpc_dir;
 };
 
 static struct global Globals;
@@ -362,7 +390,7 @@ struct service {
        bool valid;
        bool autoloaded;
        int usershare;
-       time_t usershare_last_mod;
+       struct timespec usershare_last_mod;
        char *szService;
        char *szPath;
        char *szUsername;
@@ -506,7 +534,7 @@ static struct service sDefault = {
        True,                   /* valid */
        False,                  /* not autoloaded */
        0,                      /* not a usershare */
-       (time_t)0,              /* No last mod time */
+       {0, },                  /* No last mod time */
        NULL,                   /* szService */
        NULL,                   /* szPath */
        NULL,                   /* szUsername */
@@ -599,7 +627,7 @@ static struct service sDefault = {
        True,                   /* bLevel2OpLocks */
        False,                  /* bOnlyUser */
        True,                   /* bMangledNames */
-       True,                   /* bWidelinks */
+       false,                  /* bWidelinks */
        True,                   /* bSymlinks */
        False,                  /* bSyncAlways */
        False,                  /* bStrictAllocate */
@@ -657,7 +685,6 @@ static int *invalid_services = NULL;
 static int num_invalid_services = 0;
 static bool bInGlobalSection = True;
 static bool bGlobalOnly = False;
-static int server_role;
 static int default_server_announce;
 
 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
@@ -676,15 +703,16 @@ static bool handle_charset( int snum, const char *pszParmValue, char **ptr );
 static bool handle_printing( int snum, const char *pszParmValue, char **ptr);
 static bool handle_ldap_debug_level( int snum, const char *pszParmValue, char **ptr);
 
-static void set_server_role(void);
 static void set_default_server_announce_type(void);
 static void set_allowed_client_auth(void);
 
 static void *lp_local_ptr(struct service *service, void *ptr);
 
 static void add_to_file_list(const char *fname, const char *subfname);
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
 
 static const struct enum_list enum_protocol[] = {
+       {PROTOCOL_SMB2, "SMB2"},
        {PROTOCOL_NT1, "NT1"},
        {PROTOCOL_LANMAN2, "LANMAN2"},
        {PROTOCOL_LANMAN1, "LANMAN1"},
@@ -739,6 +767,20 @@ static const struct enum_list enum_ldap_ssl[] = {
        {-1, NULL}
 };
 
+/* LDAP Dereferencing Alias types */
+#define SAMBA_LDAP_DEREF_NEVER         0
+#define SAMBA_LDAP_DEREF_SEARCHING     1
+#define SAMBA_LDAP_DEREF_FINDING       2
+#define SAMBA_LDAP_DEREF_ALWAYS                3
+
+static const struct enum_list enum_ldap_deref[] = {
+       {SAMBA_LDAP_DEREF_NEVER, "never"},
+       {SAMBA_LDAP_DEREF_SEARCHING, "searching"},
+       {SAMBA_LDAP_DEREF_FINDING, "finding"},
+       {SAMBA_LDAP_DEREF_ALWAYS, "always"},
+       {-1, "auto"}
+};
+
 static const struct enum_list enum_ldap_passwd_sync[] = {
        {LDAP_PASSWD_SYNC_OFF, "no"},
        {LDAP_PASSWD_SYNC_OFF, "off"},
@@ -794,12 +836,6 @@ static const struct enum_list enum_bool_auto[] = {
        {-1, NULL}
 };
 
-/* Client-side offline caching policy types */
-#define CSC_POLICY_MANUAL 0
-#define CSC_POLICY_DOCUMENTS 1
-#define CSC_POLICY_PROGRAMS 2
-#define CSC_POLICY_DISABLE 3
-
 static const struct enum_list enum_csc_policy[] = {
        {CSC_POLICY_MANUAL, "manual"},
        {CSC_POLICY_DOCUMENTS, "documents"},
@@ -1041,7 +1077,7 @@ static struct parm_struct parm_table[] = {
                .ptr            = &Globals.ConfigBackend,
                .special        = NULL,
                .enum_list      = enum_config_backend,
-               .flags          = FLAG_ADVANCED,
+               .flags          = FLAG_HIDE|FLAG_ADVANCED|FLAG_META,
        },
 
        {N_("Security Options"), P_SEP, P_SEPARATOR},
@@ -1073,15 +1109,6 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
        },
-       {
-               .label          = "update encrypted",
-               .type           = P_BOOL,
-               .p_class        = P_GLOBAL,
-               .ptr            = &Globals.bUpdateEncrypt,
-               .special        = NULL,
-               .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED,
-       },
        {
                .label          = "client schannel",
                .type           = P_ENUM,
@@ -2054,6 +2081,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "log writeable files on exit",
+               .type           = P_BOOL,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.bLogWriteableFilesOnExit,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "acl compatibility",
                .type           = P_ENUM,
@@ -2496,7 +2532,7 @@ static struct parm_struct parm_table[] = {
                .ptr            = &sDefault.iWriteCacheSize,
                .special        = NULL,
                .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED,
+               .flags          = FLAG_ADVANCED | FLAG_SHARE,
        },
        {
                .label          = "name cache timeout",
@@ -2534,6 +2570,51 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
        },
+       {
+               .label          = "ctdb timeout",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ctdb_timeout,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
+       },
+       {
+               .label          = "ctdb locktime warn threshold",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ctdb_locktime_warn_threshold,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
+       },
+       {
+               .label          = "smb2 max read",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ismb2_max_read,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
+       {
+               .label          = "smb2 max write",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ismb2_max_write,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
+       {
+               .label          = "smb2 max trans",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ismb2_max_trans,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
 
        {N_("Printing Options"), P_SEP, P_SEPARATOR},
 
@@ -3207,6 +3288,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "username map cache time",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.iUsernameMapCacheTime,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "logon script",
                .type           = P_STRING,
@@ -3258,6 +3348,8 @@ static struct parm_struct parm_table[] = {
                .type           = P_LIST,
                .p_class        = P_GLOBAL,
                .ptr            = &Globals.szInitLogonDelayedHosts,
+               .special        = NULL,
+               .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
 
@@ -3266,6 +3358,8 @@ static struct parm_struct parm_table[] = {
                .type           = P_INTEGER,
                .p_class        = P_GLOBAL,
                .ptr            = &Globals.InitLogonDelay,
+               .special        = NULL,
+               .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
 
        },
@@ -3650,6 +3744,24 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "ldap deref",
+               .type           = P_ENUM,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ldap_deref,
+               .special        = NULL,
+               .enum_list      = enum_ldap_deref,
+               .flags          = FLAG_ADVANCED,
+       },
+       {
+               .label          = "ldap follow referral",
+               .type           = P_ENUM,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ldap_follow_referral,
+               .special        = NULL,
+               .enum_list      = enum_bool_auto,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "ldap timeout",
                .type           = P_INTEGER,
@@ -3753,7 +3865,7 @@ static struct parm_struct parm_table[] = {
                .ptr            = &Globals.szConfigFile,
                .special        = NULL,
                .enum_list      = NULL,
-               .flags          = FLAG_HIDE,
+               .flags          = FLAG_HIDE|FLAG_META,
        },
        {
                .label          = "preload",
@@ -3937,6 +4049,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "nmbd bind explicit broadcast",
+               .type           = P_BOOL,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.bNmbdBindExplicitBroadcast,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "homedir map",
                .type           = P_STRING,
@@ -4016,7 +4137,7 @@ static struct parm_struct parm_table[] = {
                .ptr            = &sDefault.szInclude,
                .special        = handle_include,
                .enum_list      = NULL,
-               .flags          = FLAG_HIDE,
+               .flags          = FLAG_HIDE|FLAG_META,
        },
        {
                .label          = "preexec",
@@ -4277,7 +4398,25 @@ static struct parm_struct parm_table[] = {
                .ptr            = &sDefault.bFakeDirCreateTimes,
                .special        = NULL,
                .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
+       },
+       {
+               .label          = "async smb echo handler",
+               .type           = P_BOOL,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.bAsyncSMBEchoHandler,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
+       },
+       {
+               .label          = "multicast dns register",
+               .type           = P_BOOL,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.bMulticastDnsRegister,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
        },
        {
                .label          = "panic action",
@@ -4371,10 +4510,10 @@ static struct parm_struct parm_table[] = {
                .flags          = FLAG_ADVANCED,
        },
        {
-               .label          = "idmap alloc backend",
-               .type           = P_STRING,
+               .label          = "idmap read only",
+               .type           = P_BOOL,
                .p_class        = P_GLOBAL,
-               .ptr            = &Globals.szIdmapAllocBackend,
+               .ptr            = &Globals.bIdmapReadOnly,
                .special        = NULL,
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
@@ -4478,6 +4617,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "winbind max clients",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.winbind_max_clients,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "winbind enum users",
                .type           = P_BOOL,
@@ -4577,6 +4725,24 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "create krb5 conf",
+               .type           = P_BOOL,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.bCreateKrb5Conf,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
+       {
+               .label          = "ncalrpc dir",
+               .type           = P_STRING,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ncalrpc_dir,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
 
        {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
 };
@@ -4701,6 +4867,22 @@ static int max_open_files(void)
 #endif
 #endif
 
+       if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
+               DEBUG(2,("max_open_files: sysctl_max (%d) below "
+                       "minimum Windows limit (%d)\n",
+                       sysctl_max,
+                       MIN_OPEN_FILES_WINDOWS));
+               sysctl_max = MIN_OPEN_FILES_WINDOWS;
+       }
+
+       if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
+               DEBUG(2,("rlimit_max: rlimit_max (%d) below "
+                       "minimum Windows limit (%d)\n",
+                       rlimit_max,
+                       MIN_OPEN_FILES_WINDOWS));
+               rlimit_max = MIN_OPEN_FILES_WINDOWS;
+       }
+
        return MIN(sysctl_max, rlimit_max);
 }
 
@@ -4794,18 +4976,80 @@ static void free_global_parameters(void)
        free_parameters_by_snum(GLOBAL_SECTION_SNUM);
 }
 
+static int map_parameter(const char *pszParmName);
+
+struct lp_stored_option {
+       struct lp_stored_option *prev, *next;
+       const char *label;
+       const char *value;
+};
+
+static struct lp_stored_option *stored_options;
+
+/*
+  save options set by lp_set_cmdline() into a list. This list is
+  re-applied when we do a globals reset, so that cmdline set options
+  are sticky across reloads of smb.conf
+ */
+static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
+{
+       struct lp_stored_option *entry, *entry_next;
+       for (entry = stored_options; entry != NULL; entry = entry_next) {
+               entry_next = entry->next;
+               if (strcmp(pszParmName, entry->label) == 0) {
+                       DLIST_REMOVE(stored_options, entry);
+                       talloc_free(entry);
+                       break;
+               }
+       }
+
+       entry = talloc(NULL, struct lp_stored_option);
+       if (!entry) {
+               return false;
+       }
+
+       entry->label = talloc_strdup(entry, pszParmName);
+       if (!entry->label) {
+               talloc_free(entry);
+               return false;
+       }
+
+       entry->value = talloc_strdup(entry, pszParmValue);
+       if (!entry->value) {
+               talloc_free(entry);
+               return false;
+       }
+
+       DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
+
+       return true;
+}
+
+static bool apply_lp_set_cmdline(void)
+{
+       struct lp_stored_option *entry = NULL;
+       for (entry = stored_options; entry != NULL; entry = entry->next) {
+               if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
+                       DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
+                                 entry->label, entry->value));
+                       return false;
+               }
+       }
+       return true;
+}
+
 /***************************************************************************
  Initialise the global parameter structure.
 ***************************************************************************/
 
-static void init_globals(bool first_time_only)
+static void init_globals(bool reinit_globals)
 {
        static bool done_init = False;
        char *s = NULL;
        int i;
 
         /* If requested to initialize only once and we've already done it... */
-        if (first_time_only && done_init) {
+        if (!reinit_globals && done_init) {
                 /* ... then we have nothing more to do */
                 return;
         }
@@ -4821,6 +5065,10 @@ static void init_globals(bool first_time_only)
                free_global_parameters();
        }
 
+       /* This memset and the free_global_parameters() above will
+        * wipe out smb.conf options set with lp_set_cmdline().  The
+        * apply_lp_set_cmdline() call puts these values back in the
+        * table once the defaults are set */
        memset((void *)&Globals, '\0', sizeof(Globals));
 
        for (i = 0; parm_table[i].label; i++) {
@@ -4880,6 +5128,11 @@ static void init_globals(bool first_time_only)
        string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
        string_set(&Globals.szPidDir, get_dyn_PIDDIR());
        string_set(&Globals.szSocketAddress, "0.0.0.0");
+       /*
+        * By default support explicit binding to broadcast
+        * addresses.
+        */
+       Globals.bNmbdBindExplicitBroadcast = true;
 
        if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
                smb_panic("init_globals: ENOMEM");
@@ -4945,7 +5198,7 @@ static void init_globals(bool first_time_only)
        Globals.bTimestampLogs = True;
        string_set(&Globals.szLogLevel, "0");
        Globals.bDebugPrefixTimestamp = False;
-       Globals.bDebugHiresTimestamp = False;
+       Globals.bDebugHiresTimestamp = true;
        Globals.bDebugPid = False;
        Globals.bDebugUid = False;
        Globals.bDebugClass = False;
@@ -4994,12 +5247,14 @@ static void init_globals(bool first_time_only)
 #endif
        Globals.bUnixExtensions = True;
        Globals.bResetOnZeroVC = False;
+       Globals.bLogWriteableFilesOnExit = False;
+       Globals.bCreateKrb5Conf = true;
 
        /* hostname lookups can be very expensive and are broken on
           a large number of sites (tridge) */
        Globals.bHostnameLookups = False;
 
-       string_set(&Globals.szPassdbBackend, "smbpasswd");
+       string_set(&Globals.szPassdbBackend, "tdbsam");
        string_set(&Globals.szLdapSuffix, "");
        string_set(&Globals.szLdapMachineSuffix, "");
        string_set(&Globals.szLdapUserSuffix, "");
@@ -5009,9 +5264,11 @@ static void init_globals(bool first_time_only)
        string_set(&Globals.szLdapAdminDn, "");
        Globals.ldap_ssl = LDAP_SSL_START_TLS;
        Globals.ldap_ssl_ads = False;
+       Globals.ldap_deref = -1;
        Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
        Globals.ldap_delete_dn = False;
        Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
+       Globals.ldap_follow_referral = Auto;
        Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
        Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
        Globals.ldap_page_size = LDAP_PAGE_SIZE;
@@ -5056,6 +5313,7 @@ static void init_globals(bool first_time_only)
 
        Globals.bAllowTrustedDomains = True;
        string_set(&Globals.szIdmapBackend, "tdb");
+       Globals.bIdmapReadOnly = false;
 
        string_set(&Globals.szTemplateShell, "/bin/false");
        string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
@@ -5067,16 +5325,19 @@ static void init_globals(bool first_time_only)
        string_set(&Globals.ctdbdSocket, "");
        Globals.szClusterAddresses = NULL;
        Globals.clustering = False;
+       Globals.ctdb_timeout = 0;
+       Globals.ctdb_locktime_warn_threshold = 0;
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
+       Globals.winbind_max_clients = 200;
        Globals.bWinbindEnumUsers = False;
        Globals.bWinbindEnumGroups = False;
        Globals.bWinbindUseDefaultDomain = False;
        Globals.bWinbindTrustedDomainsOnly = False;
        Globals.bWinbindNestedGroups = True;
        Globals.winbind_expand_groups = 1;
-       Globals.szWinbindNssInfo = str_list_make_v3(talloc_autofree_context(), "template", NULL);
+       Globals.szWinbindNssInfo = str_list_make_v3(NULL, "template", NULL);
        Globals.bWinbindRefreshTickets = False;
        Globals.bWinbindOfflineLogon = False;
 
@@ -5121,6 +5382,16 @@ static void init_globals(bool first_time_only)
        Globals.iminreceivefile = 0;
 
        Globals.bMapUntrustedToDomain = false;
+       Globals.bMulticastDnsRegister = true;
+
+       Globals.ismb2_max_read = 1024*1024;
+       Globals.ismb2_max_write = 1024*1024;
+       Globals.ismb2_max_trans = 1024*1024;
+
+       string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
+
+       /* Now put back the settings that were set with lp_set_cmdline() */
+       apply_lp_set_cmdline();
 }
 
 /*******************************************************************
@@ -5142,6 +5413,9 @@ static char *lp_string(const char *s)
 #if 0
        DEBUG(10, ("lp_string(%s)\n", s));
 #endif
+       if (!s) {
+               return NULL;
+       }
 
        ret = talloc_sub_basic(ctx,
                        get_current_username(),
@@ -5192,8 +5466,6 @@ static char *lp_string(const char *s)
  bool fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
-#define FN_LOCAL_PARM_STRING(fn_name,val) \
- char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
 #define FN_LOCAL_CHAR(fn_name,val) \
  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
 
@@ -5262,6 +5534,7 @@ FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
+FN_GLOBAL_BOOL(lp_nmbd_bind_explicit_broadcast, &Globals.bNmbdBindExplicitBroadcast)
 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
@@ -5327,6 +5600,7 @@ FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
+FN_GLOBAL_INTEGER(lp_username_map_cache_time, &Globals.iUsernameMapCacheTime)
 
 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
 
@@ -5345,9 +5619,10 @@ FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
+FN_GLOBAL_BOOL(lp_create_krb5_conf, &Globals.bCreateKrb5Conf)
 
 FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
-FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
+FN_GLOBAL_BOOL(lp_idmap_read_only, &Globals.bIdmapReadOnly)
 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
@@ -5357,6 +5632,8 @@ FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
 FN_GLOBAL_BOOL(lp_ldap_ssl_ads, &Globals.ldap_ssl_ads)
+FN_GLOBAL_INTEGER(lp_ldap_deref, &Globals.ldap_deref)
+FN_GLOBAL_INTEGER(lp_ldap_follow_referral, &Globals.ldap_follow_referral)
 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
@@ -5379,6 +5656,8 @@ FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
+FN_GLOBAL_BOOL(lp_log_writeable_files_on_exit,
+              &Globals.bLogWriteableFilesOnExit)
 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)
@@ -5389,13 +5668,12 @@ FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
 FN_GLOBAL_LIST(lp_init_logon_delayed_hosts, &Globals.szInitLogonDelayedHosts)
 FN_GLOBAL_INTEGER(lp_init_logon_delay, &Globals.InitLogonDelay)
 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
-FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
+FN_GLOBAL_BOOL(_lp_readraw, &Globals.bReadRaw)
 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
-FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
+FN_GLOBAL_BOOL(_lp_writeraw, &Globals.bWriteRaw)
 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
-FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
@@ -5474,6 +5752,9 @@ FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
 FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend)
+FN_GLOBAL_INTEGER(lp_smb2_max_read, &Globals.ismb2_max_read)
+FN_GLOBAL_INTEGER(lp_smb2_max_write, &Globals.ismb2_max_write)
+FN_GLOBAL_INTEGER(lp_smb2_max_trans, &Globals.ismb2_max_trans)
 
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
@@ -5492,26 +5773,29 @@ FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
 int lp_cups_encrypt(void)
 {
+       int result = 0;
 #ifdef HAVE_HTTPCONNECTENCRYPT
        switch (Globals.CupsEncrypt) {
                case Auto:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_REQUIRED;
+                       result = HTTP_ENCRYPT_REQUIRED;
                        break;
                case True:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_ALWAYS;
+                       result = HTTP_ENCRYPT_ALWAYS;
                        break;
                case False:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_NEVER;
+                       result = HTTP_ENCRYPT_NEVER;
                        break;
        }
 #endif
-       return Globals.CupsEncrypt;
+       return result;
 }
 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
 FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout)
 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering)
+FN_GLOBAL_INTEGER(lp_ctdb_timeout, &Globals.ctdb_timeout)
+FN_GLOBAL_INTEGER(lp_ctdb_locktime_warn_threshold, &Globals.ctdb_locktime_warn_threshold)
 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
@@ -5571,7 +5855,6 @@ FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
-FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
@@ -5584,6 +5867,8 @@ FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
+FN_GLOBAL_BOOL(lp_async_smb_echo_handler, &Globals.bAsyncSMBEchoHandler)
+FN_GLOBAL_BOOL(lp_multicast_dns_register, &Globals.bMulticastDnsRegister)
 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
@@ -5628,6 +5913,7 @@ FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
 FN_LOCAL_CHAR(lp_magicchar, magic_char)
 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
 FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay)
+FN_GLOBAL_INTEGER(lp_winbind_max_clients, &Globals.winbind_max_clients)
 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
@@ -5635,9 +5921,10 @@ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
 FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrapping)
 
+FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
+
 /* local prototypes */
 
-static int map_parameter(const char *pszParmName);
 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
 static const char *get_boolean(bool bool_value);
 static int getservicebyname(const char *pszServiceName,
@@ -5652,7 +5939,6 @@ static void init_copymap(struct service *pservice);
 static bool hash_a_service(const char *name, int number);
 static void free_service_byindex(int iService);
 static void free_param_opts(struct param_opt_struct **popts);
-static char * canonicalize_servicename(const char *name);
 static void show_parameter(int parmIndex);
 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
 
@@ -5667,16 +5953,16 @@ static struct param_opt_struct *get_parametrics(int snum, const char *type,
        bool global_section = False;
        char* param_key;
         struct param_opt_struct *data;
-       
+
        if (snum >= iNumServices) return NULL;
-       
+
        if (snum < 0) { 
                data = Globals.param_opt;
                global_section = True;
        } else {
                data = ServicePtrs[snum]->param_opt;
        }
-    
+
        if (asprintf(&param_key, "%s:%s", type, option) == -1) {
                DEBUG(0,("asprintf failed!\n"));
                return NULL;
@@ -5704,7 +5990,7 @@ static struct param_opt_struct *get_parametrics(int snum, const char *type,
        }
 
        string_free(&param_key);
-       
+
        return NULL;
 }
 
@@ -5751,7 +6037,7 @@ static bool lp_bool(const char *s)
                MISSING_PARAMETER(lp_bool);
                return False;
        }
-       
+
        if (!set_boolean(s, &ret)) {
                DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
                return False;
@@ -5771,7 +6057,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
                MISSING_PARAMETER(lp_enum);
                return (-1);
        }
-       
+
        for (i=0; _enum[i].name; i++) {
                if (strequal(_enum[i].name,s))
                        return _enum[i].value;
@@ -5801,7 +6087,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data == NULL||data->value==NULL) {
                if (def) {
                        return lp_string(def);
@@ -5818,10 +6104,10 @@ char *lp_parm_talloc_string(int snum, const char *type, const char *option, cons
 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data == NULL||data->value==NULL)
                return def;
-               
+
        return data->value;
 }
 
@@ -5834,9 +6120,9 @@ const char **lp_parm_string_list(int snum, const char *type, const char *option,
 
        if (data == NULL||data->value==NULL)
                return (const char **)def;
-               
+
        if (data->list==NULL) {
-               data->list = str_list_make_v3(talloc_autofree_context(), data->value, NULL);
+               data->list = str_list_make_v3(NULL, data->value, NULL);
        }
 
        return (const char **)data->list;
@@ -5848,7 +6134,7 @@ const char **lp_parm_string_list(int snum, const char *type, const char *option,
 int lp_parm_int(int snum, const char *type, const char *option, int def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data && data->value && *data->value)
                return lp_int(data->value);
 
@@ -5861,7 +6147,7 @@ int lp_parm_int(int snum, const char *type, const char *option, int def)
 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data && data->value && *data->value)
                return lp_ulong(data->value);
 
@@ -5874,7 +6160,7 @@ unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsi
 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data && data->value && *data->value)
                return lp_bool(data->value);
 
@@ -5888,7 +6174,7 @@ int lp_parm_enum(int snum, const char *type, const char *option,
                 const struct enum_list *_enum, int def)
 {
        struct param_opt_struct *data = get_parametrics(snum, type, option);
-       
+
        if (data && data->value && *data->value && _enum)
                return lp_enum(data->value, _enum);
 
@@ -5952,7 +6238,7 @@ static void free_service(struct service *pservice)
        free_parameters(pservice);
 
        string_free(&pservice->szService);
-       bitmap_free(pservice->copymap);
+       TALLOC_FREE(pservice->copymap);
 
        free_param_opts(&pservice->param_opt);
 
@@ -5977,8 +6263,9 @@ static void free_service_byindex(int idx)
 
        if (ServicePtrs[idx]->szService) {
                char *canon_name = canonicalize_servicename(
+                       talloc_tos(),
                        ServicePtrs[idx]->szService );
-               
+
                dbwrap_delete_bystring(ServiceHash, canon_name );
                TALLOC_FREE(canon_name);
        }
@@ -6003,9 +6290,6 @@ static int add_a_service(const struct service *pservice, const char *name)
        if (name) {
                i = getservicebyname(name, NULL);
                if (i >= 0) {
-                       /* Clean all parametric options for service */
-                       /* They will be added during parsing again */
-                       free_param_opts(&ServicePtrs[i]->param_opt);
                        return (i);
                }
        }
@@ -6020,7 +6304,7 @@ static int add_a_service(const struct service *pservice, const char *name)
        if (i == iNumServices) {
                struct service **tsp;
                int *tinvalid;
-               
+
                tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct service *, num_to_alloc);
                if (tsp == NULL) {
                        DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
@@ -6053,14 +6337,14 @@ static int add_a_service(const struct service *pservice, const char *name)
        copy_service(ServicePtrs[i], &tservice, NULL);
        if (name)
                string_set(&ServicePtrs[i]->szService, name);
-               
+
        DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
                i, ServicePtrs[i]->szService));
 
        if (!hash_a_service(ServicePtrs[i]->szService, i)) {
                return (-1);
        }
-               
+
        return (i);
 }
 
@@ -6068,7 +6352,7 @@ static int add_a_service(const struct service *pservice, const char *name)
   Convert a string to uppercase and remove whitespaces.
 ***************************************************************************/
 
-static char *canonicalize_servicename(const char *src)
+char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
 {
        char *result;
 
@@ -6077,7 +6361,7 @@ static char *canonicalize_servicename(const char *src)
                return NULL;
        }
 
-       result = talloc_strdup(talloc_tos(), src);
+       result = talloc_strdup(ctx, src);
        SMB_ASSERT(result != NULL);
 
        strlower_m(result);
@@ -6104,7 +6388,7 @@ static bool hash_a_service(const char *name, int idx)
        DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
                idx, name));
 
-       canon_name = canonicalize_servicename( name );
+       canon_name = canonicalize_servicename(talloc_tos(), name );
 
        dbwrap_store_bystring(ServiceHash, canon_name,
                              make_tdb_data((uint8 *)&idx, sizeof(idx)),
@@ -6125,6 +6409,11 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
 {
        int i;
 
+       if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
+                       pszHomedir[0] == '\0') {
+               return false;
+       }
+
        i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
 
        if (i < 0)
@@ -6238,7 +6527,7 @@ bool lp_add_printer(const char *pszPrintername, int iDefaultService)
        ServicePtrs[i]->bOpLocks = False;
        /* Printer services must be printable. */
        ServicePtrs[i]->bPrint_ok = True;
-       
+
        DEBUG(3, ("adding printer service %s\n", pszPrintername));
 
        return (True);
@@ -6606,7 +6895,7 @@ static int getservicebyname(const char *pszServiceName, struct service *pservice
                return -1;
        }
 
-       canon_name = canonicalize_servicename(pszServiceName);
+       canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
 
        data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
 
@@ -6635,7 +6924,8 @@ static int getservicebyname(const char *pszServiceName, struct service *pservice
  */
 static void set_param_opt(struct param_opt_struct **opt_list,
                          const char *opt_name,
-                         const char *opt_value)
+                         const char *opt_value,
+                         unsigned flags)
 {
        struct param_opt_struct *new_opt, *opt;
        bool not_added;
@@ -6651,9 +6941,16 @@ static void set_param_opt(struct param_opt_struct **opt_list,
        while (opt) {
                /* If we already have same option, override it */
                if (strwicmp(opt->key, opt_name) == 0) {
+                       if ((opt->flags & FLAG_CMDLINE) &&
+                           !(flags & FLAG_CMDLINE)) {
+                               /* it's been marked as not to be
+                                  overridden */
+                               return;
+                       }
                        string_free(&opt->value);
                        TALLOC_FREE(opt->list);
                        opt->value = SMB_STRDUP(opt_value);
+                       opt->flags = flags;
                        not_added = false;
                        break;
                }
@@ -6664,6 +6961,7 @@ static void set_param_opt(struct param_opt_struct **opt_list,
            new_opt->key = SMB_STRDUP(opt_name);
            new_opt->value = SMB_STRDUP(opt_value);
            new_opt->list = NULL;
+           new_opt->flags = flags;
            DLIST_ADD(*opt_list, new_opt);
        }
 }
@@ -6728,10 +7026,10 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS
                        bitmap_copy(pserviceDest->copymap,
                                    pserviceSource->copymap);
        }
-       
+
        data = pserviceSource->param_opt;
        while (data) {
-               set_param_opt(&pserviceDest->param_opt, data->key, data->value);
+               set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->flags);
                data = data->next;
        }
 }
@@ -6964,6 +7262,7 @@ static void add_to_file_list(const char *fname, const char *subfname)
                }
                f->subfname = SMB_STRDUP(subfname);
                if (!f->subfname) {
+                       SAFE_FREE(f->name);
                        SAFE_FREE(f);
                        return;
                }
@@ -6974,6 +7273,7 @@ static void add_to_file_list(const char *fname, const char *subfname)
                if (t)
                        f->modtime = t;
        }
+       return;
 }
 
 /**
@@ -7023,7 +7323,6 @@ bool lp_file_list_changed(void)
        DEBUG(6, ("lp_file_list_changed()\n"));
 
        while (f) {
-               char *n2 = NULL;
                time_t mod_time;
 
                if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
@@ -7039,9 +7338,11 @@ bool lp_file_list_changed(void)
                                return true;
                        }
                } else {
-                       n2 = alloc_sub_basic(get_current_username(),
-                                           current_user_info.domain,
-                                           f->name);
+                       char *n2 = NULL;
+                       n2 = talloc_sub_basic(talloc_tos(),
+                                             get_current_username(),
+                                             current_user_info.domain,
+                                             f->name);
                        if (!n2) {
                                return false;
                        }
@@ -7060,12 +7361,11 @@ bool lp_file_list_changed(void)
                                          ctime(&mod_time)));
                                f->modtime = mod_time;
                                SAFE_FREE(f->subfname);
-                               f->subfname = n2; /* Passing ownership of
-                                                    return from alloc_sub_basic
-                                                    above. */
+                               f->subfname = SMB_STRDUP(n2);
+                               TALLOC_FREE(n2);
                                return true;
                        }
-                       SAFE_FREE(n2);
+                       TALLOC_FREE(n2);
                }
                f = f->next;
        }
@@ -7082,12 +7382,12 @@ bool lp_file_list_changed(void)
 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
 {
        bool ret;
-       char *netbios_name = alloc_sub_basic(get_current_username(),
-                                       current_user_info.domain,
-                                       pszParmValue);
+       char *netbios_name = talloc_sub_basic(
+               talloc_tos(), get_current_username(), current_user_info.domain,
+               pszParmValue);
 
        ret = set_global_myname(netbios_name);
-       SAFE_FREE(netbios_name);
+       TALLOC_FREE(netbios_name);
        string_set(&Globals.szNetbiosName,global_myname());
 
        DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
@@ -7110,17 +7410,17 @@ static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
 {
        bool ret;
-       
+
        ret = set_global_myworkgroup(pszParmValue);
        string_set(&Globals.szWorkgroup,lp_workgroup());
-       
+
        return ret;
 }
 
 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
 {
        bool ret;
-       
+
        ret = set_global_scope(pszParmValue);
        string_set(&Globals.szNetbiosScope,global_scope());
 
@@ -7130,7 +7430,7 @@ static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
 {
        TALLOC_FREE(Globals.szNetbiosAliases);
-       Globals.szNetbiosAliases = str_list_make_v3(talloc_autofree_context(), pszParmValue, NULL);
+       Globals.szNetbiosAliases = str_list_make_v3(NULL, pszParmValue, NULL);
        return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
 }
 
@@ -7166,9 +7466,9 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr)
                }
        }
 
-       fname = alloc_sub_basic(get_current_username(),
-                               current_user_info.domain,
-                               pszParmValue);
+       fname = talloc_sub_basic(talloc_tos(), get_current_username(),
+                                current_user_info.domain,
+                                pszParmValue);
 
        add_to_file_list(pszParmValue, fname);
 
@@ -7179,12 +7479,12 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr)
                include_depth++;
                ret = pm_process(fname, do_section, do_parameter, NULL);
                include_depth--;
-               SAFE_FREE(fname);
+               TALLOC_FREE(fname);
                return ret;
        }
 
        DEBUG(2, ("Can't find include file %s\n", fname));
-       SAFE_FREE(fname);
+       TALLOC_FREE(fname);
        return true;
 }
 
@@ -7425,10 +7725,10 @@ static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
 static void init_copymap(struct service *pservice)
 {
        int i;
-       if (pservice->copymap) {
-               bitmap_free(pservice->copymap);
-       }
-       pservice->copymap = bitmap_allocate(NUMPARAMETERS);
+
+       TALLOC_FREE(pservice->copymap);
+
+       pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
        if (!pservice->copymap)
                DEBUG(0,
                      ("Couldn't allocate copymap!! (size %d)\n",
@@ -7485,11 +7785,17 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
 
                opt_list = (snum < 0)
                        ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
-               set_param_opt(opt_list, pszParmName, pszParmValue);
+               set_param_opt(opt_list, pszParmName, pszParmValue, 0);
 
                return (True);
        }
 
+       /* if it's already been set by the command line, then we don't
+          override here */
+       if (parm_table[parmnum].flags & FLAG_CMDLINE) {
+               return true;
+       }
+
        if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
                DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
                          pszParmName));
@@ -7556,7 +7862,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                case P_LIST:
                        TALLOC_FREE(*((char ***)parm_ptr));
                        *(char ***)parm_ptr = str_list_make_v3(
-                               talloc_autofree_context(), pszParmValue, NULL);
+                               NULL, pszParmValue, NULL);
                        break;
 
                case P_STRING:
@@ -7578,6 +7884,46 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
        return (True);
 }
 
+/***************************************************************************
+set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
+FLAG_CMDLINE won't be overridden by loads from smb.conf.
+***************************************************************************/
+
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
+{
+       int parmnum;
+       parmnum = map_parameter(pszParmName);
+       if (parmnum >= 0) {
+               parm_table[parmnum].flags &= ~FLAG_CMDLINE;
+               if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
+                       return false;
+               }
+               parm_table[parmnum].flags |= FLAG_CMDLINE;
+
+               if (store_values) {
+                       store_lp_set_cmdline(pszParmName, pszParmValue);
+               }
+               return true;
+       }
+
+       /* it might be parametric */
+       if (strchr(pszParmName, ':') != NULL) {
+               set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
+               if (store_values) {
+                       store_lp_set_cmdline(pszParmName, pszParmValue);
+               }
+               return true;
+       }
+
+       DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
+       return true;
+}
+
+bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
+{
+       return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
+}
+
 /***************************************************************************
  Process a parameter.
 ***************************************************************************/
@@ -7594,7 +7940,33 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue,
                                pszParmName, pszParmValue));
 }
 
-/***************************************************************************
+/*
+  set a option from the commandline in 'a=b' format. Use to support --option
+*/
+bool lp_set_option(const char *option)
+{
+       char *p, *s;
+       bool ret;
+
+       s = talloc_strdup(NULL, option);
+       if (!s) {
+               return false;
+       }
+
+       p = strchr(s, '=');
+       if (!p) {
+               talloc_free(s);
+               return false;
+       }
+
+       *p = 0;
+
+       ret = lp_set_cmdline(s, p+1);
+       talloc_free(s);
+       return ret;
+}
+
+/**************************************************************************
  Print a parameter of the specified type.
 ***************************************************************************/
 
@@ -7753,6 +8125,9 @@ static bool do_section(const char *pszSectionName, void *userdata)
                        DEBUG(0, ("Failed to add a new service\n"));
                        return (False);
                }
+               /* Clean all parametric options for service */
+               /* They will be added during parsing again */
+               free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
        }
 
        return (bRetval);
@@ -7801,11 +8176,12 @@ static void dump_globals(FILE *f)
 {
        int i;
        struct param_opt_struct *data;
-       
+
        fprintf(f, "[global]\n");
 
        for (i = 0; parm_table[i].label; i++)
                if (parm_table[i].p_class == P_GLOBAL &&
+                   !(parm_table[i].flags & FLAG_META) &&
                    parm_table[i].ptr &&
                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
                        if (defaults_saved && is_default(i))
@@ -7845,18 +8221,18 @@ static void dump_a_service(struct service *pService, FILE * f)
 {
        int i;
        struct param_opt_struct *data;
-       
+
        if (pService != &sDefault)
                fprintf(f, "[%s]\n", pService->szService);
 
        for (i = 0; parm_table[i].label; i++) {
 
                if (parm_table[i].p_class == P_LOCAL &&
+                   !(parm_table[i].flags & FLAG_META) &&
                    parm_table[i].ptr &&
                    (*parm_table[i].label != '-') &&
                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
                {
-               
                        int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
 
                        if (pService == &sDefault) {
@@ -7928,6 +8304,7 @@ bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
 
        for (i = 0; parm_table[i].label; i++) {
                if (strwicmp(parm_table[i].label, parm_name) == 0 &&
+                   !(parm_table[i].flags & FLAG_META) &&
                    (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
                    parm_table[i].ptr &&
                    (*parm_table[i].label != '-') &&
@@ -7992,7 +8369,7 @@ struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
                            && (parm_table[*i].ptr ==
                                parm_table[(*i) - 1].ptr))
                                continue;
-                       
+
                        if (is_default(*i) && !allparameters)
                                continue;
 
@@ -8093,7 +8470,7 @@ static void lp_add_auto_services(char *str)
 
                home = get_user_home_dir(talloc_tos(), p);
 
-               if (home && homes >= 0)
+               if (home && home[0] && homes >= 0)
                        lp_add_home(p, homes, p, home);
 
                TALLOC_FREE(home);
@@ -8217,79 +8594,6 @@ static void lp_save_defaults(void)
        defaults_saved = True;
 }
 
-/*******************************************************************
- Set the server type we will announce as via nmbd.
-********************************************************************/
-
-static const struct srv_role_tab {
-       uint32 role;
-       const char *role_str;
-} srv_role_tab [] = {
-       { ROLE_STANDALONE, "ROLE_STANDALONE" },
-       { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
-       { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
-       { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
-       { 0, NULL }
-};
-
-const char* server_role_str(uint32 role)
-{
-       int i = 0;
-       for (i=0; srv_role_tab[i].role_str; i++) {
-               if (role == srv_role_tab[i].role) {
-                       return srv_role_tab[i].role_str;
-               }
-       }
-       return NULL;
-}
-
-static void set_server_role(void)
-{
-       server_role = ROLE_STANDALONE;
-
-       switch (lp_security()) {
-               case SEC_SHARE:
-                       if (lp_domain_logons())
-                               DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
-                       break;
-               case SEC_SERVER:
-                       if (lp_domain_logons())
-                               DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
-                       /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
-                       server_role = ROLE_STANDALONE;
-                       break;
-               case SEC_DOMAIN:
-                       if (lp_domain_logons()) {
-                               DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
-                               server_role = ROLE_DOMAIN_BDC;
-                               break;
-                       }
-                       server_role = ROLE_DOMAIN_MEMBER;
-                       break;
-               case SEC_ADS:
-                       if (lp_domain_logons()) {
-                               server_role = ROLE_DOMAIN_PDC;
-                               break;
-                       }
-                       server_role = ROLE_DOMAIN_MEMBER;
-                       break;
-               case SEC_USER:
-                       if (lp_domain_logons()) {
-
-                               if (Globals.iDomainMaster) /* auto or yes */ 
-                                       server_role = ROLE_DOMAIN_PDC;
-                               else
-                                       server_role = ROLE_DOMAIN_BDC;
-                       }
-                       break;
-               default:
-                       DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
-                       break;
-       }
-
-       DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
-}
-
 /***********************************************************
  If we should send plaintext/LANMAN passwords in the clinet
 ************************************************************/
@@ -8323,29 +8627,30 @@ static void set_allowed_client_auth(void)
  get their sorry ass fired.
 ***************************************************************************/
 
-static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
+static bool check_usershare_stat(const char *fname,
+                                const SMB_STRUCT_STAT *psbuf)
 {
-       if (!S_ISREG(psbuf->st_mode)) {
+       if (!S_ISREG(psbuf->st_ex_mode)) {
                DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
                        "not a regular file\n",
-                       fname, (unsigned int)psbuf->st_uid ));
+                       fname, (unsigned int)psbuf->st_ex_uid ));
                return False;
        }
 
        /* Ensure this doesn't have the other write bit set. */
-       if (psbuf->st_mode & S_IWOTH) {
+       if (psbuf->st_ex_mode & S_IWOTH) {
                DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
                        "public write. Refusing to allow as a usershare file.\n",
-                       fname, (unsigned int)psbuf->st_uid ));
+                       fname, (unsigned int)psbuf->st_ex_uid ));
                return False;
        }
 
        /* Should be 10k or less. */
-       if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
+       if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
                DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
                        "too large (%u) to be a user share file.\n",
-                       fname, (unsigned int)psbuf->st_uid,
-                       (unsigned int)psbuf->st_size ));
+                       fname, (unsigned int)psbuf->st_ex_uid,
+                       (unsigned int)psbuf->st_ex_size ));
                return False;
        }
 
@@ -8364,7 +8669,8 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
                        int numlines,
                        char **pp_sharepath,
                        char **pp_comment,
-                       SEC_DESC **ppsd,
+                       char **pp_cp_servicename,
+                       struct security_descriptor **ppsd,
                        bool *pallow_guest)
 {
        const char **prefixallowlist = lp_usershare_prefix_allow_list();
@@ -8431,6 +8737,27 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
                if (lines[4][9] == 'y') {
                        *pallow_guest = True;
                }
+
+               /* Backwards compatible extension to file version #2. */
+               if (numlines > 5) {
+                       if (strncmp(lines[5], "sharename=", 10) != 0) {
+                               return USERSHARE_MALFORMED_SHARENAME_DEF;
+                       }
+                       if (!strequal(&lines[5][10], servicename)) {
+                               return USERSHARE_BAD_SHARENAME;
+                       }
+                       *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
+                       if (!*pp_cp_servicename) {
+                               return USERSHARE_POSIX_ERR;
+                       }
+               }
+       }
+
+       if (*pp_cp_servicename == NULL) {
+               *pp_cp_servicename = talloc_strdup(ctx, servicename);
+               if (!*pp_cp_servicename) {
+                       return USERSHARE_POSIX_ERR;
+               }
        }
 
        if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
@@ -8495,7 +8822,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
        /* Ensure the owner of the usershare file has permission to share
           this directory. */
 
-       if (sys_stat(sharepath, &sbuf) == -1) {
+       if (sys_stat(sharepath, &sbuf, false) == -1) {
                DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
                        servicename, sharepath, strerror(errno) ));
                sys_closedir(dp);
@@ -8504,7 +8831,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
 
        sys_closedir(dp);
 
-       if (!S_ISDIR(sbuf.st_mode)) {
+       if (!S_ISDIR(sbuf.st_ex_mode)) {
                DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
                        servicename, sharepath ));
                return USERSHARE_PATH_NOT_DIRECTORY;
@@ -8516,7 +8843,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
 
        if (lp_usershare_owner_only()) {
                /* root can share anything. */
-               if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
+               if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
                        return USERSHARE_PATH_NOT_ALLOWED;
                }
        }
@@ -8542,47 +8869,52 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        char *fname = NULL;
        char *sharepath = NULL;
        char *comment = NULL;
-       fstring service_name;
+       char *cp_service_name = NULL;
        char **lines = NULL;
        int numlines = 0;
        int fd = -1;
        int iService = -1;
-       TALLOC_CTX *ctx = NULL;
-       SEC_DESC *psd = NULL;
+       TALLOC_CTX *ctx = talloc_stackframe();
+       struct security_descriptor *psd = NULL;
        bool guest_ok = False;
+       char *canon_name = NULL;
+       bool added_service = false;
+       int ret = -1;
 
        /* Ensure share name doesn't contain invalid characters. */
        if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
                DEBUG(0,("process_usershare_file: share name %s contains "
                        "invalid characters (any of %s)\n",
                        file_name, INVALID_SHARENAME_CHARS ));
-               return -1;
+               goto out;
        }
 
-       fstrcpy(service_name, file_name);
+       canon_name = canonicalize_servicename(ctx, file_name);
+       if (!canon_name) {
+               goto out;
+       }
 
-       if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
+       fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
+       if (!fname) {
+               goto out;
        }
 
        /* Minimize the race condition by doing an lstat before we
           open and fstat. Ensure this isn't a symlink link. */
 
-       if (sys_lstat(fname, &lsbuf) != 0) {
+       if (sys_lstat(fname, &lsbuf, false) != 0) {
                DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
                        fname, strerror(errno) ));
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        /* This must be a regular file, not a symlink, directory or
           other strange filetype. */
        if (!check_usershare_stat(fname, &lsbuf)) {
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        {
-               char *canon_name = canonicalize_servicename(service_name);
                TDB_DATA data = dbwrap_fetch_bystring(
                        ServiceHash, canon_name, canon_name);
 
@@ -8591,16 +8923,17 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
                if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
                        iService = *(int *)data.dptr;
                }
-               TALLOC_FREE(canon_name);
        }
 
-       if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
+       if (iService != -1 &&
+           timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
+                            &lsbuf.st_ex_mtime) == 0) {
                /* Nothing changed - Mark valid and return. */
                DEBUG(10,("process_usershare_file: service %s not changed.\n",
-                       service_name ));
+                       canon_name ));
                ServicePtrs[iService]->usershare = USERSHARE_VALID;
-               SAFE_FREE(fname);
-               return iService;
+               ret = iService;
+               goto out;
        }
 
        /* Try and open the file read only - no symlinks allowed. */
@@ -8613,33 +8946,29 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        if (fd == -1) {
                DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
                        fname, strerror(errno) ));
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        /* Now fstat to be *SURE* it's a regular file. */
-       if (sys_fstat(fd, &sbuf) != 0) {
+       if (sys_fstat(fd, &sbuf, false) != 0) {
                close(fd);
                DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
                        fname, strerror(errno) ));
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        /* Is it the same dev/inode as was lstated ? */
-       if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
+       if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) {
                close(fd);
                DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
                        "Symlink spoofing going on ?\n", fname ));
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        /* This must be a regular file, not a symlink, directory or
           other strange filetype. */
        if (!check_usershare_stat(fname, &sbuf)) {
-               SAFE_FREE(fname);
-               return -1;
+               goto out;
        }
 
        lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
@@ -8647,30 +8976,17 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        close(fd);
        if (lines == NULL) {
                DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
-                       fname, (unsigned int)sbuf.st_uid ));
-               SAFE_FREE(fname);
-               return -1;
-       }
-
-       SAFE_FREE(fname);
-
-       /* Should we allow printers to be shared... ? */
-       ctx = talloc_init("usershare_sd_xctx");
-       if (!ctx) {
-               TALLOC_FREE(lines);
-               return 1;
+                       fname, (unsigned int)sbuf.st_ex_uid ));
+               goto out;
        }
 
-       if (parse_usershare_file(ctx, &sbuf, service_name,
+       if (parse_usershare_file(ctx, &sbuf, file_name,
                        iService, lines, numlines, &sharepath,
-                       &comment, &psd, &guest_ok) != USERSHARE_OK) {
-               talloc_destroy(ctx);
-               TALLOC_FREE(lines);
-               return -1;
+                       &comment, &cp_service_name,
+                       &psd, &guest_ok) != USERSHARE_OK) {
+               goto out;
        }
 
-       TALLOC_FREE(lines);
-
        /* Everything ok - add the service possibly using a template. */
        if (iService < 0) {
                const struct service *sp = &sDefault;
@@ -8678,25 +8994,24 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
                        sp = ServicePtrs[snum_template];
                }
 
-               if ((iService = add_a_service(sp, service_name)) < 0) {
+               if ((iService = add_a_service(sp, cp_service_name)) < 0) {
                        DEBUG(0, ("process_usershare_file: Failed to add "
-                               "new service %s\n", service_name));
-                       talloc_destroy(ctx);
-                       return -1;
+                               "new service %s\n", cp_service_name));
+                       goto out;
                }
 
+               added_service = true;
+
                /* Read only is controlled by usershare ACL below. */
                ServicePtrs[iService]->bRead_only = False;
        }
 
        /* Write the ACL of the new/modified share. */
-       if (!set_share_security(service_name, psd)) {
+       if (!set_share_security(canon_name, psd)) {
                 DEBUG(0, ("process_usershare_file: Failed to set share "
                        "security for user share %s\n",
-                       service_name ));
-               lp_remove_service(iService);
-               talloc_destroy(ctx);
-               return -1;
+                       canon_name ));
+               goto out;
        }
 
        /* If from a template it may be marked invalid. */
@@ -8711,20 +9026,28 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        }
 
        /* And note when it was loaded. */
-       ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
+       ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
        string_set(&ServicePtrs[iService]->szPath, sharepath);
        string_set(&ServicePtrs[iService]->comment, comment);
 
-       talloc_destroy(ctx);
+       ret = iService;
+
+  out:
+
+       if (ret == -1 && iService != -1 && added_service) {
+               lp_remove_service(iService);
+       }
 
-       return iService;
+       TALLOC_FREE(lines);
+       TALLOC_FREE(ctx);
+       return ret;
 }
 
 /***************************************************************************
  Checks if a usershare entry has been modified since last load.
 ***************************************************************************/
 
-static bool usershare_exists(int iService, time_t *last_mod)
+static bool usershare_exists(int iService, struct timespec *last_mod)
 {
        SMB_STRUCT_STAT lsbuf;
        const char *usersharepath = Globals.szUsersharePath;
@@ -8736,18 +9059,18 @@ static bool usershare_exists(int iService, time_t *last_mod)
                return false;
        }
 
-       if (sys_lstat(fname, &lsbuf) != 0) {
+       if (sys_lstat(fname, &lsbuf, false) != 0) {
                SAFE_FREE(fname);
                return false;
        }
 
-       if (!S_ISREG(lsbuf.st_mode)) {
+       if (!S_ISREG(lsbuf.st_ex_mode)) {
                SAFE_FREE(fname);
                return false;
        }
 
        SAFE_FREE(fname);
-       *last_mod = lsbuf.st_mtime;
+       *last_mod = lsbuf.st_ex_mtime;
        return true;
 }
 
@@ -8766,13 +9089,13 @@ int load_usershare_service(const char *servicename)
                return -1;
        }
 
-       if (sys_stat(usersharepath, &sbuf) != 0) {
+       if (sys_stat(usersharepath, &sbuf, false) != 0) {
                DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
                        usersharepath, strerror(errno) ));
                return -1;
        }
 
-       if (!S_ISDIR(sbuf.st_mode)) {
+       if (!S_ISDIR(sbuf.st_ex_mode)) {
                DEBUG(0,("load_usershare_service: %s is not a directory.\n",
                        usersharepath ));
                return -1;
@@ -8784,9 +9107,9 @@ int load_usershare_service(const char *servicename)
         */
 
 #ifdef S_ISVTX
-       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+       if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
 #else
-       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+       if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
 #endif
                DEBUG(0,("load_usershare_service: directory %s is not owned by root "
                        "or does not have the sticky bit 't' set or is writable by anyone.\n",
@@ -8843,7 +9166,7 @@ int load_usershare_shares(void)
                return lp_numservices();
        }
 
-       if (sys_stat(usersharepath, &sbuf) != 0) {
+       if (sys_stat(usersharepath, &sbuf, false) != 0) {
                DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
                        usersharepath, strerror(errno) ));
                return ret;
@@ -8855,9 +9178,9 @@ int load_usershare_shares(void)
         */
 
 #ifdef S_ISVTX
-       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+       if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
 #else
-       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+       if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
 #endif
                DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
                        "or does not have the sticky bit 't' set or is writable by anyone.\n",
@@ -9026,13 +9349,13 @@ bool lp_is_in_client(void)
  False on failure.
 ***************************************************************************/
 
-bool lp_load_ex(const char *pszFname,
-               bool global_only,
-               bool save_defaults,
-               bool add_ipc,
-               bool initialize_globals,
-               bool allow_include_registry,
-               bool allow_registry_shares)
+static bool lp_load_ex(const char *pszFname,
+                      bool global_only,
+                      bool save_defaults,
+                      bool add_ipc,
+                      bool initialize_globals,
+                      bool allow_include_registry,
+                      bool allow_registry_shares)
 {
        char *n2 = NULL;
        bool bRetval;
@@ -9045,9 +9368,11 @@ bool lp_load_ex(const char *pszFname,
        bGlobalOnly = global_only;
        bAllowIncludeRegistry = allow_include_registry;
 
-       init_globals(initialize_globals);
+       init_globals(initialize_globals);
        debug_init();
 
+       free_file_list();
+
        if (save_defaults) {
                init_locals();
                lp_save_defaults();
@@ -9059,7 +9384,7 @@ bool lp_load_ex(const char *pszFname,
        iServiceIndex = -1;
 
        if (lp_config_backend_is_file()) {
-               n2 = alloc_sub_basic(get_current_username(),
+               n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
                                        current_user_info.domain,
                                        pszFname);
                if (!n2) {
@@ -9069,7 +9394,7 @@ bool lp_load_ex(const char *pszFname,
                add_to_file_list(pszFname, n2);
 
                bRetval = pm_process(n2, do_section, do_parameter, NULL);
-               SAFE_FREE(n2);
+               TALLOC_FREE(n2);
 
                /* finish up the last section */
                DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
@@ -9091,7 +9416,7 @@ bool lp_load_ex(const char *pszFname,
                        /* start over */
                        DEBUG(1, ("lp_load_ex: changing to config backend "
                                  "registry\n"));
-                       init_globals(false);
+                       init_globals(true);
                        lp_kill_all_services();
                        return lp_load_ex(pszFname, global_only, save_defaults,
                                          add_ipc, initialize_globals,
@@ -9151,18 +9476,19 @@ bool lp_load(const char *pszFname,
                          save_defaults,
                          add_ipc,
                          initialize_globals,
-                         true, false);
+                         true,   /* allow_include_registry */
+                         false); /* allow_registry_shares*/
 }
 
 bool lp_load_initial_only(const char *pszFname)
 {
        return lp_load_ex(pszFname,
-                         true,
-                         false,
-                         false,
-                         true,
-                         false,
-                         false);
+                         true,   /* global only */
+                         false,  /* save_defaults */
+                         false,  /* add_ipc */
+                         true,   /* initialize_globals */
+                         false,  /* allow_include_registry */
+                         false); /* allow_registry_shares*/
 }
 
 bool lp_load_with_registry_shares(const char *pszFname,
@@ -9176,8 +9502,8 @@ bool lp_load_with_registry_shares(const char *pszFname,
                          save_defaults,
                          add_ipc,
                          initialize_globals,
-                         true,
-                         true);
+                         true,  /* allow_include_registry */
+                         true); /* allow_registry_shares*/
 }
 
 /***************************************************************************
@@ -9234,11 +9560,11 @@ int lp_servicenumber(const char *pszServiceName)
 {
        int iService;
         fstring serviceName;
-        
+
         if (!pszServiceName) {
                return GLOBAL_SECTION_SNUM;
        }
-        
+
        for (iService = iNumServices - 1; iService >= 0; iService--) {
                if (VALID(iService) && ServicePtrs[iService]->szService) {
                        /*
@@ -9256,7 +9582,7 @@ int lp_servicenumber(const char *pszServiceName)
        }
 
        if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
-               time_t last_mod;
+               struct timespec last_mod;
 
                if (!usershare_exists(iService, &last_mod)) {
                        /* Remove the share security tdb entry for it. */
@@ -9268,7 +9594,8 @@ int lp_servicenumber(const char *pszServiceName)
                }
 
                /* Has it been modified ? If so delete and reload. */
-               if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
+               if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
+                                    &last_mod) < 0) {
                        /* Remove it from the array. */
                        free_service_byindex(iService);
                        /* and now reload it. */
@@ -9387,7 +9714,7 @@ const char *volume_label(int snum)
        if (!*label) {
                label = lp_servicename(snum);
        }
-               
+
        /* This returns a 33 byte guarenteed null terminated string. */
        ret = talloc_strndup(talloc_tos(), label, 32);
        if (!ret) {
@@ -9452,24 +9779,27 @@ static void set_default_server_announce_type(void)
 }
 
 /***********************************************************
- returns role of Samba server
+ If we are PDC then prefer us as DMB
 ************************************************************/
 
-int lp_server_role(void)
+bool lp_domain_master(void)
 {
-       return server_role;
+       if (Globals.iDomainMaster == Auto)
+               return (lp_server_role() == ROLE_DOMAIN_PDC);
+
+       return (bool)Globals.iDomainMaster;
 }
 
 /***********************************************************
  If we are PDC then prefer us as DMB
 ************************************************************/
 
-bool lp_domain_master(void)
+bool lp_domain_master_true_or_auto(void)
 {
-       if (Globals.iDomainMaster == Auto)
-               return (lp_server_role() == ROLE_DOMAIN_PDC);
+       if (Globals.iDomainMaster) /* auto or yes */
+               return true;
 
-       return (bool)Globals.iDomainMaster;
+       return false;
 }
 
 /***********************************************************
@@ -9659,7 +9989,7 @@ bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
        bool sign_active = false;
 
        /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
-       if (Protocol < PROTOCOL_NT1) {
+       if (get_Protocol() < PROTOCOL_NT1) {
                return false;
        }
        if (signing_state) {
@@ -9760,9 +10090,62 @@ int lp_min_receive_file_size(void)
 const char *lp_socket_address(void)
 {
        char *sock_addr = Globals.szSocketAddress;
-       
+
        if (sock_addr[0] == '\0'){
                string_set(&Globals.szSocketAddress, "0.0.0.0");
        }
        return  Globals.szSocketAddress;
 }
+
+void lp_set_passdb_backend(const char *backend)
+{
+       string_set(&Globals.szPassdbBackend, backend);
+}
+
+/*******************************************************************
+ Safe wide links checks.
+ This helper function always verify the validity of wide links,
+ even after a configuration file reload.
+********************************************************************/
+
+static bool lp_widelinks_internal(int snum)
+{
+       return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
+                       sDefault.bWidelinks);
+}
+
+void widelinks_warning(int snum)
+{
+       if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
+               DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
+                       "These parameters are incompatible. "
+                       "Wide links will be disabled for this share.\n",
+                       lp_servicename(snum) ));
+       }
+}
+
+bool lp_widelinks(int snum)
+{
+       /* wide links is always incompatible with unix extensions */
+       if (lp_unix_extensions()) {
+               return false;
+       }
+
+       return lp_widelinks_internal(snum);
+}
+
+bool lp_writeraw(void)
+{
+       if (lp_async_smb_echo_handler()) {
+               return false;
+       }
+       return _lp_writeraw();
+}
+
+bool lp_readraw(void)
+{
+       if (lp_async_smb_echo_handler()) {
+               return false;
+       }
+       return _lp_readraw();
+}