2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
8 Copyright (C) Simo Sorce 2001
9 Copyright (C) Alexander Bokovoy 2002
10 Copyright (C) Stefan (metze) Metzmacher 2002
11 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
12 Copyright (C) James Myers 2003 <myersjj@samba.org>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 * This module provides suitable callback functions for the params
33 * module. It builds the internal table of service details which is
34 * then used by the rest of the server.
38 * 1) add it to the global or service structure definition
39 * 2) add it to the parm_table
40 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41 * 4) If it's a global then initialise it in init_globals. If a local
42 * (ie. service) parameter then initialise it in the sDefault structure
46 * The configuration file is processed sequentially for speed. It is NOT
47 * accessed randomly as happens in 'real' Windows. For this reason, there
48 * is a fair bit of sequence-dependent code here - ie., code which assumes
49 * that certain things happen before others. In particular, the code which
50 * happens at the boundary between sections is delicately poised, so be
57 #include "dynconfig.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "smb_server/smb_server.h"
63 #include "libcli/raw/signing.h"
64 #include "lib/util/dlinklist.h"
65 #include "param/loadparm.h"
67 static BOOL bLoaded = False;
69 #define standard_sub_basic(str,len)
71 /* some helpful bits */
72 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
73 #define VALID(i) ServicePtrs[i]->valid
75 static BOOL do_parameter(const char *, const char *, void *);
76 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
78 static BOOL defaults_saved = False;
82 struct param_opt *prev, *next;
89 * This structure describes global (ie., server-wide) parameters.
99 char *display_charset;
104 char *szServerString;
105 char *szAutoServices;
108 char *szShareBackend;
112 char *szWINS_CONFIG_URL;
116 char *jsonrpcServicesDir;
117 char **szPasswordServers;
118 char *szSocketOptions;
120 char **szWINSservers;
122 char *szSocketAddress;
123 char *szAnnounceVersion; /* This is initialised in init_globals */
126 char **szNetbiosAliases;
127 char *szNetbiosScope;
128 char *szDomainOtherSIDs;
129 char **szNameResolveOrder;
130 char **dcerpc_ep_servers;
131 char **server_services;
132 char *ntptr_providor;
133 char *szWinbindSeparator;
134 char *szWinbinddSocketDirectory;
135 int bWinbindSealedPipes;
136 char *webapps_directory;
152 int paranoid_server_security;
155 int announce_as; /* This is initialised in init_globals */
162 char *socket_options;
167 int bPreferredMaster;
168 int bEncryptPasswords;
170 int bObeyPamRestrictions;
175 int bBindInterfacesOnly;
177 int bNTStatusSupport;
183 int bClientPlaintextAuth;
184 int bClientLanManAuth;
185 int bClientNTLMv2Auth;
186 int client_use_spnego_principal;
192 struct param_opt *param_opt;
196 static global Globals;
199 * This structure describes a single service.
214 char **ntvfs_handler;
230 struct param_opt *param_opt;
232 char dummy[3]; /* for alignment */
237 /* This is a default service used to prime a services structure */
238 static service sDefault = {
240 NULL, /* szService */
243 NULL, /* szInclude */
244 NULL, /* szPrintername */
245 NULL, /* szHostsallow */
246 NULL, /* szHostsdeny */
250 NULL, /* ntvfs_handler */
251 1000, /* iMaxPrintJobs */
252 0, /* iMaxConnections */
254 True, /* bAvailable */
255 True, /* bBrowseable */
256 True, /* bRead_only */
257 False, /* bPrint_ok */
258 False, /* bMap_system */
259 False, /* bMap_hidden */
260 True, /* bMap_archive */
261 True, /* bStrictLocking */
263 False, /* bMSDfsRoot */
264 False, /* bStrictSync */
265 False, /* bCIFileSystem */
266 NULL, /* Parametric options */
271 /* local variables */
272 static service **ServicePtrs = NULL;
273 static int iNumServices = 0;
274 static int iServiceIndex = 0;
275 static BOOL bInGlobalSection = True;
277 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
279 /* prototypes for the special type handlers */
280 static BOOL handle_include(const char *pszParmValue, char **ptr);
281 static BOOL handle_copy(const char *pszParmValue, char **ptr);
283 static const struct enum_list enum_protocol[] = {
284 {PROTOCOL_SMB2, "SMB2"},
285 {PROTOCOL_NT1, "NT1"},
286 {PROTOCOL_LANMAN2, "LANMAN2"},
287 {PROTOCOL_LANMAN1, "LANMAN1"},
288 {PROTOCOL_CORE, "CORE"},
289 {PROTOCOL_COREPLUS, "COREPLUS"},
290 {PROTOCOL_COREPLUS, "CORE+"},
294 static const struct enum_list enum_security[] = {
295 {SEC_SHARE, "SHARE"},
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
309 static const struct enum_list enum_bool_auto[] = {
320 /* Client-side offline caching policy types */
321 #define CSC_POLICY_MANUAL 0
322 #define CSC_POLICY_DOCUMENTS 1
323 #define CSC_POLICY_PROGRAMS 2
324 #define CSC_POLICY_DISABLE 3
326 static const struct enum_list enum_csc_policy[] = {
327 {CSC_POLICY_MANUAL, "manual"},
328 {CSC_POLICY_DOCUMENTS, "documents"},
329 {CSC_POLICY_PROGRAMS, "programs"},
330 {CSC_POLICY_DISABLE, "disable"},
334 /* SMB signing types. */
335 static const struct enum_list enum_smb_signing_vals[] = {
336 {SMB_SIGNING_OFF, "No"},
337 {SMB_SIGNING_OFF, "False"},
338 {SMB_SIGNING_OFF, "0"},
339 {SMB_SIGNING_OFF, "Off"},
340 {SMB_SIGNING_OFF, "disabled"},
341 {SMB_SIGNING_SUPPORTED, "Yes"},
342 {SMB_SIGNING_SUPPORTED, "True"},
343 {SMB_SIGNING_SUPPORTED, "1"},
344 {SMB_SIGNING_SUPPORTED, "On"},
345 {SMB_SIGNING_SUPPORTED, "enabled"},
346 {SMB_SIGNING_REQUIRED, "required"},
347 {SMB_SIGNING_REQUIRED, "mandatory"},
348 {SMB_SIGNING_REQUIRED, "force"},
349 {SMB_SIGNING_REQUIRED, "forced"},
350 {SMB_SIGNING_REQUIRED, "enforced"},
351 {SMB_SIGNING_AUTO, "auto"},
355 static const struct enum_list enum_server_role[] = {
356 {ROLE_STANDALONE, "standalone"},
357 {ROLE_DOMAIN_MEMBER, "member server"},
358 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
363 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
365 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
366 * is implied in current control logic. This may change at some later time. A
367 * flag value of 0 means - show as development option only.
369 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
370 * screen in SWAT. This is used to exclude parameters as well as to squash all
371 * parameters that have been duplicated by pseudonyms.
373 static struct parm_struct parm_table[] = {
374 {"Base Options", P_SEP, P_SEPARATOR},
376 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
378 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
379 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
383 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
385 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
386 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
394 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
395 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
396 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
398 {"Security Options", P_SEP, P_SEPARATOR},
400 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
404 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"secrets database", P_STRING, P_GLOBAL, &Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
423 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
424 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
426 {"Logging Options", P_SEP, P_SEPARATOR},
428 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
430 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"Protocol Options", P_SEP, P_SEPARATOR},
434 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"web application directory", P_STRING, P_GLOBAL, &Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
449 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
451 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
453 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
454 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
455 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
456 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
461 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
462 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
463 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
466 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
471 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
472 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
473 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
475 {"Tuning Options", P_SEP, P_SEPARATOR},
477 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
478 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
479 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
481 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
482 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
484 {"Printing Options", P_SEP, P_SEPARATOR},
486 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
487 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
488 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
490 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
491 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
493 {"Filename Handling", P_SEP, P_SEPARATOR},
495 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
497 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
499 {"Domain Options", P_SEP, P_SEPARATOR},
501 {"Logon Options", P_SEP, P_SEPARATOR},
504 {"Browse Options", P_SEP, P_SEPARATOR},
506 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
507 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
508 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
509 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
510 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
512 {"WINS Options", P_SEP, P_SEPARATOR},
514 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
515 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
516 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
517 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
519 {"Locking Options", P_SEP, P_SEPARATOR},
521 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
523 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
525 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
527 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
528 {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
532 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"jsonrpc services directory", P_STRING, P_GLOBAL, &Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
540 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
542 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
543 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
545 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
546 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
547 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
549 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
552 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
554 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
555 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
557 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
562 return the parameter table
564 struct parm_struct *lp_parm_table(void)
569 /***************************************************************************
570 Initialise the global parameter structure.
571 ***************************************************************************/
572 static void init_globals(void)
577 DEBUG(3, ("Initialising global parameters\n"));
579 for (i = 0; parm_table[i].label; i++) {
580 if ((parm_table[i].type == P_STRING ||
581 parm_table[i].type == P_USTRING) &&
583 !(parm_table[i].flags & FLAG_CMDLINE)) {
584 string_set(parm_table[i].ptr, "");
588 do_parameter("config file", dyn_CONFIGFILE, NULL);
590 do_parameter("share backend", "classic", NULL);
592 do_parameter("server role", "standalone", NULL);
594 /* options that can be set on the command line must be initialised via
595 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
597 do_parameter("socket options", "TCP_NODELAY", NULL);
599 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
600 myname = get_myname();
601 do_parameter("netbios name", myname, NULL);
603 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
605 do_parameter("fstype", FSTYPE_STRING, NULL);
606 do_parameter("ntvfs handler", "unixuid default", NULL);
607 do_parameter("max connections", "-1", NULL);
609 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo", NULL);
610 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind", NULL);
611 do_parameter("ntptr providor", "simple_ldb", NULL);
612 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
613 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
614 do_parameter("sam database", "sam.ldb", NULL);
615 do_parameter("secrets database", "secrets.ldb", NULL);
616 do_parameter("spoolss database", "spoolss.ldb", NULL);
617 do_parameter("wins config database", "wins_config.ldb", NULL);
618 do_parameter("wins database", "wins.ldb", NULL);
619 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
621 /* This hive should be dynamically generated by Samba using
622 data from the sam, but for the moment leave it in a tdb to
623 keep regedt32 from popping up an annoying dialog. */
624 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
626 /* using UTF8 by default allows us to support all chars */
627 do_parameter("unix charset", "UTF8", NULL);
629 /* Use codepage 850 as a default for the dos character set */
630 do_parameter("dos charset", "CP850", NULL);
633 * Allow the default PASSWD_CHAT to be overridden in local.h.
635 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
637 do_parameter("pid directory", dyn_PIDDIR, NULL);
638 do_parameter("lock dir", dyn_LOCKDIR, NULL);
639 do_parameter("modules dir", dyn_MODULESDIR, NULL);
640 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
642 do_parameter("socket address", "0.0.0.0", NULL);
643 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
645 do_parameter_var("announce version", "%d.%d",
646 DEFAULT_MAJOR_VERSION,
647 DEFAULT_MINOR_VERSION);
649 do_parameter("password server", "*", NULL);
651 do_parameter("max mux", "50", NULL);
652 do_parameter("max xmit", "12288", NULL);
653 do_parameter("password level", "0", NULL);
654 do_parameter("LargeReadwrite", "True", NULL);
655 do_parameter("server min protocol", "CORE", NULL);
656 do_parameter("server max protocol", "NT1", NULL);
657 do_parameter("client min protocol", "CORE", NULL);
658 do_parameter("client max protocol", "NT1", NULL);
659 do_parameter("security", "USER", NULL);
660 do_parameter("paranoid server security", "True", NULL);
661 do_parameter("EncryptPasswords", "True", NULL);
662 do_parameter("ReadRaw", "True", NULL);
663 do_parameter("WriteRaw", "True", NULL);
664 do_parameter("NullPasswords", "False", NULL);
665 do_parameter("ObeyPamRestrictions", "False", NULL);
666 do_parameter("announce as", "NT SERVER", NULL);
668 do_parameter("TimeServer", "False", NULL);
669 do_parameter("BindInterfacesOnly", "False", NULL);
670 do_parameter("Unicode", "True", NULL);
671 do_parameter("ClientLanManAuth", "True", NULL);
672 do_parameter("LanmanAuth", "True", NULL);
673 do_parameter("NTLMAuth", "True", NULL);
674 do_parameter("client use spnego principal", "False", NULL);
676 do_parameter("UnixExtensions", "False", NULL);
678 do_parameter("PreferredMaster", "Auto", NULL);
679 do_parameter("LocalMaster", "True", NULL);
681 do_parameter("wins support", "False", NULL);
682 do_parameter("dns proxy", "True", NULL);
684 do_parameter("winbind separator", "\\", NULL);
685 do_parameter("winbind sealed pipes", "True", NULL);
686 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
688 do_parameter("client signing", "Yes", NULL);
689 do_parameter("server signing", "auto", NULL);
691 do_parameter("use spnego", "True", NULL);
693 do_parameter("smb ports", "445 139", NULL);
694 do_parameter("nbt port", "137", NULL);
695 do_parameter("dgram port", "138", NULL);
696 do_parameter("cldap port", "389", NULL);
697 do_parameter("krb5 port", "88", NULL);
698 do_parameter("kpasswd port", "464", NULL);
699 do_parameter("web port", "901", NULL);
700 do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
701 do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
703 do_parameter("nt status support", "True", NULL);
705 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
706 do_parameter("min wins ttl", "10", NULL);
708 do_parameter("tls enabled", "True", NULL);
709 do_parameter("tls keyfile", "tls/key.pem", NULL);
710 do_parameter("tls certfile", "tls/cert.pem", NULL);
711 do_parameter("tls cafile", "tls/ca.pem", NULL);
712 do_parameter_var("js include", "%s", dyn_JSDIR);
713 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
715 for (i = 0; parm_table[i].label; i++) {
716 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
717 parm_table[i].flags |= FLAG_DEFAULT;
722 static TALLOC_CTX *lp_talloc;
724 /******************************************************************* a
725 Free up temporary memory - called from the main loop.
726 ********************************************************************/
728 void lp_talloc_free(void)
732 talloc_free(lp_talloc);
736 /*******************************************************************
737 Convenience routine to grab string parameters into temporary memory
738 and run standard_sub_basic on them. The buffers can be written to by
739 callers without affecting the source string.
740 ********************************************************************/
742 static const char *lp_string(const char *s)
744 #if 0 /* until REWRITE done to make thread-safe */
745 size_t len = s ? strlen(s) : 0;
749 /* The follow debug is useful for tracking down memory problems
750 especially if you have an inner loop that is calling a lp_*()
751 function that returns a string. Perhaps this debug should be
752 present all the time? */
755 DEBUG(10, ("lp_string(%s)\n", s));
758 #if 0 /* until REWRITE done to make thread-safe */
760 lp_talloc = talloc_init("lp_talloc");
762 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
770 strlcpy(ret, s, len);
772 if (trim_string(ret, "\"", "\"")) {
773 if (strchr(ret,'"') != NULL)
774 strlcpy(ret, s, len);
777 standard_sub_basic(ret,len+100);
784 In this section all the functions that are used to access the
785 parameters from the rest of the program are defined
788 #define FN_GLOBAL_STRING(fn_name,ptr) \
789 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
790 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
791 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
792 #define FN_GLOBAL_LIST(fn_name,ptr) \
793 const char **fn_name(void) {return(*(const char ***)(ptr));}
794 #define FN_GLOBAL_BOOL(fn_name,ptr) \
795 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
797 #define FN_GLOBAL_CHAR(fn_name,ptr) \
798 char fn_name(void) {return(*(char *)(ptr));}
800 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
801 int fn_name(void) {return(*(int *)(ptr));}
803 #define FN_LOCAL_STRING(fn_name,val) \
804 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
805 #define FN_LOCAL_CONST_STRING(fn_name,val) \
806 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
807 #define FN_LOCAL_LIST(fn_name,val) \
808 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
809 #define FN_LOCAL_BOOL(fn_name,val) \
810 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
812 #define FN_LOCAL_CHAR(fn_name,val) \
813 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
815 #define FN_LOCAL_INTEGER(fn_name,val) \
816 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
818 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
819 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
820 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
821 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
822 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
823 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
824 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
825 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
826 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
827 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &Globals.webapps_directory)
828 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
829 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
830 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
834 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
835 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &Globals.szSECRETS_URL)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
843 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
844 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
845 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
853 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
854 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
856 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
857 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
858 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
859 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
860 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
865 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
866 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
867 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
868 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
870 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
872 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
873 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
874 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
879 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
880 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
881 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
882 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
886 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
887 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
895 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
896 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
897 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
898 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
899 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
900 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
901 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
902 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
903 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
904 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
905 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
906 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
907 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
908 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
909 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir)
912 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
913 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
914 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
915 static FN_LOCAL_STRING(_lp_printername, szPrintername)
916 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
917 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
918 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
919 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
920 static FN_LOCAL_STRING(lp_volume, volume)
921 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
922 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
923 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
924 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
925 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
926 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
927 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
928 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
929 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
930 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
931 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
932 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
933 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
934 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
935 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
937 /* local prototypes */
939 static int map_parameter(const char *pszParmName);
940 static int getservicebyname(const char *pszServiceName,
941 service * pserviceDest);
942 static void copy_service(service * pserviceDest,
943 service * pserviceSource, int *pcopymapDest);
944 static BOOL service_ok(int iService);
945 static BOOL do_section(const char *pszSectionName, void *);
946 static void init_copymap(service * pservice);
948 /* This is a helper function for parametrical options support. */
949 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
950 /* Actual parametrical functions are quite simple */
951 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
954 struct param_opt *data;
956 if (lookup_service >= iNumServices) return NULL;
958 data = (lookup_service < 0) ?
959 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
961 asprintf(&vfskey, "%s:%s", type, option);
965 if (strcmp(data->key, vfskey) == 0) {
972 if (lookup_service >= 0) {
973 /* Try to fetch the same option but from globals */
974 /* but only if we are not already working with Globals */
975 data = Globals.param_opt;
977 if (strcmp(data->key, vfskey) == 0) {
991 /*******************************************************************
992 convenience routine to return int parameters.
993 ********************************************************************/
994 static int lp_int(const char *s)
998 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1002 return strtol(s, NULL, 0);
1005 /*******************************************************************
1006 convenience routine to return unsigned long parameters.
1007 ********************************************************************/
1008 static int lp_ulong(const char *s)
1012 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1016 return strtoul(s, NULL, 0);
1019 /*******************************************************************
1020 convenience routine to return unsigned long parameters.
1021 ********************************************************************/
1022 static double lp_double(const char *s)
1026 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1030 return strtod(s, NULL);
1033 /*******************************************************************
1034 convenience routine to return boolean parameters.
1035 ********************************************************************/
1036 static BOOL lp_bool(const char *s)
1041 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1045 if (!set_boolean(s, &ret)) {
1046 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1054 /* Return parametric option from a given service. Type is a part of option before ':' */
1055 /* Parametric option has following syntax: 'Type: option = value' */
1056 /* Returned value is allocated in 'lp_talloc' context */
1058 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1060 const char *value = lp_get_parametric(lookup_service, type, option);
1063 return lp_string(value);
1068 /* Return parametric option from a given service. Type is a part of option before ':' */
1069 /* Parametric option has following syntax: 'Type: option = value' */
1070 /* Returned value is allocated in 'lp_talloc' context */
1072 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1073 const char *separator)
1075 const char *value = lp_get_parametric(lookup_service, type, option);
1078 return str_list_make(talloc_autofree_context(), value, separator);
1083 /* Return parametric option from a given service. Type is a part of option before ':' */
1084 /* Parametric option has following syntax: 'Type: option = value' */
1086 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1088 const char *value = lp_get_parametric(lookup_service, type, option);
1091 return lp_int(value);
1096 /* Return parametric option from a given service. Type is a part of
1097 * option before ':'.
1098 * Parametric option has following syntax: 'Type: option = value'.
1101 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1105 const char *value = lp_get_parametric(lookup_service, type, option);
1107 if (value && conv_str_size(value, &bval)) {
1108 if (bval <= INT_MAX) {
1116 /* Return parametric option from a given service. Type is a part of option before ':' */
1117 /* Parametric option has following syntax: 'Type: option = value' */
1119 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1121 const char *value = lp_get_parametric(lookup_service, type, option);
1124 return lp_ulong(value);
1130 double lp_parm_double(int lookup_service, const char *type, const char *option, double default_v)
1132 const char *value = lp_get_parametric(lookup_service, type, option);
1135 return lp_double(value);
1140 /* Return parametric option from a given service. Type is a part of option before ':' */
1141 /* Parametric option has following syntax: 'Type: option = value' */
1143 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1145 const char *value = lp_get_parametric(lookup_service, type, option);
1148 return lp_bool(value);
1154 /***************************************************************************
1155 Initialise a service to the defaults.
1156 ***************************************************************************/
1158 static void init_service(service * pservice)
1160 memset((char *)pservice, '\0', sizeof(service));
1161 copy_service(pservice, &sDefault, NULL);
1164 /***************************************************************************
1165 Free the dynamically allocated parts of a service struct.
1166 ***************************************************************************/
1168 static void free_service(service *pservice)
1171 struct param_opt *data, *pdata;
1175 if (pservice->szService)
1176 DEBUG(5, ("free_service: Freeing service %s\n",
1177 pservice->szService));
1179 string_free(&pservice->szService);
1180 SAFE_FREE(pservice->copymap);
1182 for (i = 0; parm_table[i].label; i++) {
1183 if ((parm_table[i].type == P_STRING ||
1184 parm_table[i].type == P_USTRING) &&
1185 parm_table[i].class == P_LOCAL) {
1186 string_free((char **)
1187 (((char *)pservice) +
1188 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1189 } else if (parm_table[i].type == P_LIST &&
1190 parm_table[i].class == P_LOCAL) {
1191 char ***listp = (char ***)(((char *)pservice) +
1192 PTR_DIFF(parm_table[i].ptr, &sDefault));
1193 talloc_free(*listp);
1198 DEBUG(5,("Freeing parametrics:\n"));
1199 data = pservice->param_opt;
1201 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1202 string_free(&data->key);
1203 string_free(&data->value);
1209 ZERO_STRUCTP(pservice);
1212 /***************************************************************************
1213 Add a new service to the services array initialising it with the given
1215 ***************************************************************************/
1217 static int add_a_service(const service *pservice, const char *name)
1221 int num_to_alloc = iNumServices + 1;
1222 struct param_opt *data, *pdata;
1224 tservice = *pservice;
1226 /* it might already exist */
1228 i = getservicebyname(name, NULL);
1230 /* Clean all parametric options for service */
1231 /* They will be added during parsing again */
1232 data = ServicePtrs[i]->param_opt;
1234 string_free(&data->key);
1235 string_free(&data->value);
1240 ServicePtrs[i]->param_opt = NULL;
1245 /* find an invalid one */
1246 for (i = 0; i < iNumServices; i++)
1247 if (!ServicePtrs[i]->valid)
1250 /* if not, then create one */
1251 if (i == iNumServices) {
1254 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1257 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1262 ServicePtrs[iNumServices] = malloc_p(service);
1264 if (!ServicePtrs[iNumServices]) {
1265 DEBUG(0,("add_a_service: out of memory!\n"));
1271 free_service(ServicePtrs[i]);
1273 ServicePtrs[i]->valid = True;
1275 init_service(ServicePtrs[i]);
1276 copy_service(ServicePtrs[i], &tservice, NULL);
1278 string_set(&ServicePtrs[i]->szService, name);
1282 /***************************************************************************
1283 Add a new home service, with the specified home directory, defaults coming
1285 ***************************************************************************/
1287 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1288 const char *user, const char *pszHomedir)
1293 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1298 if (!(*(ServicePtrs[iDefaultService]->szPath))
1299 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1300 pstrcpy(newHomedir, pszHomedir);
1302 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1303 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1306 string_set(&ServicePtrs[i]->szPath, newHomedir);
1308 if (!(*(ServicePtrs[i]->comment))) {
1310 slprintf(comment, sizeof(comment) - 1,
1311 "Home directory of %s", user);
1312 string_set(&ServicePtrs[i]->comment, comment);
1314 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1315 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1317 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1323 /***************************************************************************
1324 Add a new service, based on an old one.
1325 ***************************************************************************/
1327 int lp_add_service(const char *pszService, int iDefaultService)
1329 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1332 /***************************************************************************
1333 Add the IPC service.
1334 ***************************************************************************/
1336 static BOOL lp_add_hidden(const char *name, const char *fstype)
1339 int i = add_a_service(&sDefault, name);
1344 slprintf(comment, sizeof(comment) - 1,
1345 "%s Service (%s)", fstype, Globals.szServerString);
1347 string_set(&ServicePtrs[i]->szPath, tmpdir());
1348 string_set(&ServicePtrs[i]->comment, comment);
1349 string_set(&ServicePtrs[i]->fstype, fstype);
1350 ServicePtrs[i]->iMaxConnections = -1;
1351 ServicePtrs[i]->bAvailable = True;
1352 ServicePtrs[i]->bRead_only = True;
1353 ServicePtrs[i]->bPrint_ok = False;
1354 ServicePtrs[i]->bBrowseable = False;
1356 if (strcasecmp(fstype, "IPC") == 0) {
1357 lp_do_parameter(i, "ntvfs handler", "default");
1360 DEBUG(3, ("adding hidden service %s\n", name));
1365 /***************************************************************************
1366 Add a new printer service, with defaults coming from service iFrom.
1367 ***************************************************************************/
1369 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1371 const char *comment = "From Printcap";
1372 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1377 /* note that we do NOT default the availability flag to True - */
1378 /* we take it from the default service passed. This allows all */
1379 /* dynamic printers to be disabled by disabling the [printers] */
1380 /* entry (if/when the 'available' keyword is implemented!). */
1382 /* the printer name is set to the service name. */
1383 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1384 string_set(&ServicePtrs[i]->comment, comment);
1385 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1386 /* Printers cannot be read_only. */
1387 ServicePtrs[i]->bRead_only = False;
1388 /* Printer services must be printable. */
1389 ServicePtrs[i]->bPrint_ok = True;
1391 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1396 /***************************************************************************
1397 Map a parameter's string representation to something we can use.
1398 Returns False if the parameter string is not recognised, else TRUE.
1399 ***************************************************************************/
1401 static int map_parameter(const char *pszParmName)
1405 if (*pszParmName == '-')
1408 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1409 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1412 /* Warn only if it isn't parametric option */
1413 if (strchr(pszParmName, ':') == NULL)
1414 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1415 /* We do return 'fail' for parametric options as well because they are
1416 stored in different storage
1423 return the parameter structure for a parameter
1425 struct parm_struct *lp_parm_struct(const char *name)
1427 int parmnum = map_parameter(name);
1428 if (parmnum == -1) return NULL;
1429 return &parm_table[parmnum];
1433 return the parameter pointer for a parameter
1435 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1440 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1443 /***************************************************************************
1444 Find a service by name. Otherwise works like get_service.
1445 ***************************************************************************/
1447 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1451 for (iService = iNumServices - 1; iService >= 0; iService--)
1452 if (VALID(iService) &&
1453 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1454 if (pserviceDest != NULL)
1455 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1462 /***************************************************************************
1463 Copy a service structure to another.
1464 If pcopymapDest is NULL then copy all fields
1465 ***************************************************************************/
1467 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1470 BOOL bcopyall = (pcopymapDest == NULL);
1471 struct param_opt *data, *pdata, *paramo;
1474 for (i = 0; parm_table[i].label; i++)
1475 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1476 (bcopyall || pcopymapDest[i])) {
1477 void *def_ptr = parm_table[i].ptr;
1479 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1482 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1485 switch (parm_table[i].type) {
1487 *(int *)dest_ptr = *(int *)src_ptr;
1492 *(int *)dest_ptr = *(int *)src_ptr;
1496 string_set(dest_ptr,
1501 string_set(dest_ptr,
1503 strupper(*(char **)dest_ptr);
1506 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1507 *(const char ***)src_ptr);
1515 init_copymap(pserviceDest);
1516 if (pserviceSource->copymap)
1517 memcpy((void *)pserviceDest->copymap,
1518 (void *)pserviceSource->copymap,
1519 sizeof(int) * NUMPARAMETERS);
1522 data = pserviceSource->param_opt;
1525 pdata = pserviceDest->param_opt;
1526 /* Traverse destination */
1528 /* If we already have same option, override it */
1529 if (strcmp(pdata->key, data->key) == 0) {
1530 string_free(&pdata->value);
1531 pdata->value = strdup(data->value);
1535 pdata = pdata->next;
1538 paramo = malloc_p(struct param_opt);
1541 paramo->key = strdup(data->key);
1542 paramo->value = strdup(data->value);
1543 DLIST_ADD(pserviceDest->param_opt, paramo);
1549 /***************************************************************************
1550 Check a service for consistency. Return False if the service is in any way
1551 incomplete or faulty, else True.
1552 ***************************************************************************/
1554 static BOOL service_ok(int iService)
1559 if (ServicePtrs[iService]->szService[0] == '\0') {
1560 DEBUG(0, ("The following message indicates an internal error:\n"));
1561 DEBUG(0, ("No service name in service entry.\n"));
1565 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1566 /* I can't see why you'd want a non-printable printer service... */
1567 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1568 if (!ServicePtrs[iService]->bPrint_ok) {
1569 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1570 ServicePtrs[iService]->szService));
1571 ServicePtrs[iService]->bPrint_ok = True;
1573 /* [printers] service must also be non-browsable. */
1574 if (ServicePtrs[iService]->bBrowseable)
1575 ServicePtrs[iService]->bBrowseable = False;
1578 /* If a service is flagged unavailable, log the fact at level 0. */
1579 if (!ServicePtrs[iService]->bAvailable)
1580 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1581 ServicePtrs[iService]->szService));
1586 static struct file_lists {
1587 struct file_lists *next;
1591 } *file_lists = NULL;
1593 /*******************************************************************
1594 Keep a linked list of all config files so we know when one has changed
1595 it's date and needs to be reloaded.
1596 ********************************************************************/
1598 static void add_to_file_list(const char *fname, const char *subfname)
1600 struct file_lists *f = file_lists;
1603 if (f->name && !strcmp(f->name, fname))
1609 f = malloc_p(struct file_lists);
1612 f->next = file_lists;
1613 f->name = strdup(fname);
1618 f->subfname = strdup(subfname);
1624 f->modtime = file_modtime(subfname);
1626 time_t t = file_modtime(subfname);
1632 /*******************************************************************
1633 Check if a config file has changed date.
1634 ********************************************************************/
1636 BOOL lp_file_list_changed(void)
1638 struct file_lists *f = file_lists;
1639 DEBUG(6, ("lp_file_list_changed()\n"));
1645 pstrcpy(n2, f->name);
1646 standard_sub_basic(n2,sizeof(n2));
1648 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1649 f->name, n2, ctime(&f->modtime)));
1651 mod_time = file_modtime(n2);
1653 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1655 ("file %s modified: %s\n", n2,
1657 f->modtime = mod_time;
1658 SAFE_FREE(f->subfname);
1659 f->subfname = strdup(n2);
1667 /***************************************************************************
1668 Handle the include operation.
1669 ***************************************************************************/
1671 static BOOL handle_include(const char *pszParmValue, char **ptr)
1674 pstrcpy(fname, pszParmValue);
1676 standard_sub_basic(fname,sizeof(fname));
1678 add_to_file_list(pszParmValue, fname);
1680 string_set(ptr, fname);
1682 if (file_exist(fname))
1683 return (pm_process(fname, do_section, do_parameter, NULL));
1685 DEBUG(2, ("Can't find include file %s\n", fname));
1690 /***************************************************************************
1691 Handle the interpretation of the copy parameter.
1692 ***************************************************************************/
1694 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1698 service serviceTemp;
1700 string_set(ptr, pszParmValue);
1702 init_service(&serviceTemp);
1706 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1708 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1709 if (iTemp == iServiceIndex) {
1710 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1712 copy_service(ServicePtrs[iServiceIndex],
1714 ServicePtrs[iServiceIndex]->copymap);
1718 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1722 free_service(&serviceTemp);
1726 /***************************************************************************
1727 Initialise a copymap.
1728 ***************************************************************************/
1730 static void init_copymap(service * pservice)
1733 SAFE_FREE(pservice->copymap);
1734 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1735 if (!pservice->copymap)
1737 ("Couldn't allocate copymap!! (size %d)\n",
1738 (int)NUMPARAMETERS));
1740 for (i = 0; i < NUMPARAMETERS; i++)
1741 pservice->copymap[i] = True;
1744 #if 0 /* not used anywhere */
1745 /***************************************************************************
1746 Return the local pointer to a parameter given the service number and the
1747 pointer into the default structure.
1748 ***************************************************************************/
1750 void *lp_local_ptr(int snum, void *ptr)
1752 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1756 /***************************************************************************
1757 Process a parametric option
1758 ***************************************************************************/
1759 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1761 struct param_opt *paramo, *data;
1764 while (isspace((unsigned char)*pszParmName)) {
1768 name = strdup(pszParmName);
1769 if (!name) return False;
1774 data = Globals.param_opt;
1776 data = ServicePtrs[snum]->param_opt;
1779 /* Traverse destination */
1780 for (paramo=data; paramo; paramo=paramo->next) {
1781 /* If we already have the option set, override it unless
1782 it was a command line option and the new one isn't */
1783 if (strcmp(paramo->key, name) == 0) {
1784 if ((paramo->flags & FLAG_CMDLINE) &&
1785 !(flags & FLAG_CMDLINE)) {
1789 free(paramo->value);
1790 paramo->value = strdup(pszParmValue);
1791 paramo->flags = flags;
1797 paramo = malloc_p(struct param_opt);
1800 paramo->key = strdup(name);
1801 paramo->value = strdup(pszParmValue);
1802 paramo->flags = flags;
1804 DLIST_ADD(Globals.param_opt, paramo);
1806 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1814 /***************************************************************************
1815 Process a parameter for a particular service number. If snum < 0
1816 then assume we are in the globals.
1817 ***************************************************************************/
1818 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1821 void *parm_ptr = NULL; /* where we are going to store the result */
1822 void *def_ptr = NULL;
1824 parmnum = map_parameter(pszParmName);
1827 if (strchr(pszParmName, ':')) {
1828 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1830 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1834 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1835 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1839 /* if the flag has been set on the command line, then don't allow override,
1840 but don't report an error */
1841 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1845 def_ptr = parm_table[parmnum].ptr;
1847 /* we might point at a service, the default service or a global */
1851 if (parm_table[parmnum].class == P_GLOBAL) {
1853 ("Global parameter %s found in service section!\n",
1858 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1863 if (!ServicePtrs[snum]->copymap)
1864 init_copymap(ServicePtrs[snum]);
1866 /* this handles the aliases - set the copymap for other entries with
1867 the same data pointer */
1868 for (i = 0; parm_table[i].label; i++)
1869 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1870 ServicePtrs[snum]->copymap[i] = False;
1873 /* if it is a special case then go ahead */
1874 if (parm_table[parmnum].special) {
1875 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1879 /* now switch on the type of variable it is */
1880 switch (parm_table[parmnum].type)
1884 if (!set_boolean(pszParmValue, &b)) {
1885 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1888 *(int *)parm_ptr = b;
1893 *(int *)parm_ptr = atoi(pszParmValue);
1899 if (conv_str_size(pszParmValue, &val)) {
1900 if (val <= INT_MAX) {
1901 *(int *)parm_ptr = (int)val;
1906 DEBUG(0,("lp_do_parameter(%s): value is not "
1907 "a valid size specifier!\n", pszParmValue));
1912 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1913 pszParmValue, NULL);
1917 string_set(parm_ptr, pszParmValue);
1921 string_set(parm_ptr, pszParmValue);
1922 strupper(*(char **)parm_ptr);
1926 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1929 parm_table[parmnum].enum_list[i].name)) {
1931 parm_table[parmnum].
1936 if (!parm_table[parmnum].enum_list[i].name) {
1937 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1938 pszParmValue, pszParmName));
1946 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1947 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1948 /* we have to also unset FLAG_DEFAULT on aliases */
1949 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1950 parm_table[i].flags &= ~FLAG_DEFAULT;
1952 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1953 parm_table[i].flags &= ~FLAG_DEFAULT;
1960 /***************************************************************************
1961 Process a parameter.
1962 ***************************************************************************/
1964 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1966 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1967 pszParmName, pszParmValue));
1971 variable argument do parameter
1973 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1975 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1982 s = talloc_vasprintf(NULL, fmt, ap);
1984 ret = do_parameter(pszParmName, s, NULL);
1991 set a parameter from the commandline - this is called from command line parameter
1992 parsing code. It sets the parameter then marks the parameter as unable to be modified
1993 by smb.conf processing
1995 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1997 int parmnum = map_parameter(pszParmName);
2000 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2003 if (parmnum < 0 && strchr(pszParmName, ':')) {
2004 /* set a parametric option */
2005 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2009 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2013 /* reset the CMDLINE flag in case this has been called before */
2014 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2016 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2020 parm_table[parmnum].flags |= FLAG_CMDLINE;
2022 /* we have to also set FLAG_CMDLINE on aliases */
2023 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2024 parm_table[i].flags |= FLAG_CMDLINE;
2026 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2027 parm_table[i].flags |= FLAG_CMDLINE;
2034 set a option from the commandline in 'a=b' format. Use to support --option
2036 BOOL lp_set_option(const char *option)
2054 ret = lp_set_cmdline(s, p+1);
2060 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2062 /***************************************************************************
2063 Print a parameter of the specified type.
2064 ***************************************************************************/
2066 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2072 for (i = 0; p->enum_list[i].name; i++) {
2073 if (*(int *)ptr == p->enum_list[i].value) {
2075 p->enum_list[i].name);
2082 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2087 fprintf(f, "%d", *(int *)ptr);
2091 if ((char ***)ptr && *(char ***)ptr) {
2092 char **list = *(char ***)ptr;
2094 for (; *list; list++)
2095 fprintf(f, "%s%s", *list,
2096 ((*(list+1))?", ":""));
2102 if (*(char **)ptr) {
2103 fprintf(f, "%s", *(char **)ptr);
2111 /***************************************************************************
2112 Check if two parameters are equal.
2113 ***************************************************************************/
2115 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2119 return (*((int *)ptr1) == *((int *)ptr2));
2124 return (*((int *)ptr1) == *((int *)ptr2));
2127 return str_list_equal((const char **)(*(char ***)ptr1),
2128 (const char **)(*(char ***)ptr2));
2133 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2138 return (p1 == p2 || strequal(p1, p2));
2146 /***************************************************************************
2147 Process a new section (service). At this stage all sections are services.
2148 Later we'll have special sections that permit server parameters to be set.
2149 Returns True on success, False on failure.
2150 ***************************************************************************/
2152 static BOOL do_section(const char *pszSectionName, void *userdata)
2155 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2156 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2159 /* if we've just struck a global section, note the fact. */
2160 bInGlobalSection = isglobal;
2162 /* check for multiple global sections */
2163 if (bInGlobalSection) {
2164 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2168 /* if we have a current service, tidy it up before moving on */
2171 if (iServiceIndex >= 0)
2172 bRetval = service_ok(iServiceIndex);
2174 /* if all is still well, move to the next record in the services array */
2176 /* We put this here to avoid an odd message order if messages are */
2177 /* issued by the post-processing of a previous section. */
2178 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2180 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2182 DEBUG(0, ("Failed to add a new service\n"));
2191 /***************************************************************************
2192 Determine if a partcular base parameter is currentl set to the default value.
2193 ***************************************************************************/
2195 static BOOL is_default(int i)
2197 if (!defaults_saved)
2199 switch (parm_table[i].type) {
2201 return str_list_equal((const char **)parm_table[i].def.lvalue,
2202 (const char **)(*(char ***)parm_table[i].ptr));
2205 return strequal(parm_table[i].def.svalue,
2206 *(char **)parm_table[i].ptr);
2208 return parm_table[i].def.bvalue ==
2209 *(int *)parm_table[i].ptr;
2213 return parm_table[i].def.ivalue ==
2214 *(int *)parm_table[i].ptr;
2221 /***************************************************************************
2222 Display the contents of the global structure.
2223 ***************************************************************************/
2225 static void dump_globals(FILE *f, BOOL show_defaults)
2228 struct param_opt *data;
2230 fprintf(f, "# Global parameters\n[global]\n");
2232 for (i = 0; parm_table[i].label; i++)
2233 if (parm_table[i].class == P_GLOBAL &&
2234 parm_table[i].ptr &&
2235 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2236 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2238 fprintf(f, "\t%s = ", parm_table[i].label);
2239 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2242 if (Globals.param_opt != NULL) {
2243 data = Globals.param_opt;
2245 fprintf(f, "\t%s = %s\n", data->key, data->value);
2252 /***************************************************************************
2253 Display the contents of a single services record.
2254 ***************************************************************************/
2256 static void dump_a_service(service * pService, FILE * f)
2259 struct param_opt *data;
2261 if (pService != &sDefault)
2262 fprintf(f, "\n[%s]\n", pService->szService);
2264 for (i = 0; parm_table[i].label; i++)
2265 if (parm_table[i].class == P_LOCAL &&
2266 parm_table[i].ptr &&
2267 (*parm_table[i].label != '-') &&
2268 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2269 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2271 if (pService == &sDefault) {
2272 if (defaults_saved && is_default(i))
2275 if (equal_parameter(parm_table[i].type,
2276 ((char *)pService) +
2278 ((char *)&sDefault) +
2283 fprintf(f, "\t%s = ", parm_table[i].label);
2284 print_parameter(&parm_table[i],
2285 ((char *)pService) + pdiff, f);
2288 if (pService->param_opt != NULL) {
2289 data = pService->param_opt;
2291 fprintf(f, "\t%s = %s\n", data->key, data->value);
2297 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2299 service * pService = ServicePtrs[snum];
2300 struct parm_struct *parm;
2303 parm = lp_parm_struct(parm_name);
2311 ptr = ((char *)pService) +
2312 PTR_DIFF(parm->ptr, &sDefault);
2314 print_parameter(parm,
2320 /***************************************************************************
2321 Return info about the next service in a service. snum==-1 gives the globals.
2322 Return NULL when out of parameters.
2323 ***************************************************************************/
2325 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2328 /* do the globals */
2329 for (; parm_table[*i].label; (*i)++) {
2330 if (parm_table[*i].class == P_SEPARATOR)
2331 return &parm_table[(*i)++];
2333 if (!parm_table[*i].ptr
2334 || (*parm_table[*i].label == '-'))
2338 && (parm_table[*i].ptr ==
2339 parm_table[(*i) - 1].ptr))
2342 return &parm_table[(*i)++];
2345 service *pService = ServicePtrs[snum];
2347 for (; parm_table[*i].label; (*i)++) {
2348 if (parm_table[*i].class == P_SEPARATOR)
2349 return &parm_table[(*i)++];
2351 if (parm_table[*i].class == P_LOCAL &&
2352 parm_table[*i].ptr &&
2353 (*parm_table[*i].label != '-') &&
2355 (parm_table[*i].ptr !=
2356 parm_table[(*i) - 1].ptr)))
2359 PTR_DIFF(parm_table[*i].ptr,
2362 if (allparameters ||
2363 !equal_parameter(parm_table[*i].type,
2364 ((char *)pService) +
2366 ((char *)&sDefault) +
2369 return &parm_table[(*i)++];
2379 /***************************************************************************
2380 Return TRUE if the passed service number is within range.
2381 ***************************************************************************/
2383 BOOL lp_snum_ok(int iService)
2385 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2388 /***************************************************************************
2389 Auto-load some home services.
2390 ***************************************************************************/
2392 static void lp_add_auto_services(const char *str)
2397 /***************************************************************************
2398 Have we loaded a services file yet?
2399 ***************************************************************************/
2401 BOOL lp_loaded(void)
2406 /***************************************************************************
2407 Unload unused services.
2408 ***************************************************************************/
2410 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2413 for (i = 0; i < iNumServices; i++) {
2417 if (!snumused || !snumused(smb, i)) {
2418 ServicePtrs[i]->valid = False;
2419 free_service(ServicePtrs[i]);
2424 /***************************************************************************
2426 ***************************************************************************/
2428 void lp_killservice(int iServiceIn)
2430 if (VALID(iServiceIn)) {
2431 ServicePtrs[iServiceIn]->valid = False;
2432 free_service(ServicePtrs[iServiceIn]);
2436 /***************************************************************************
2437 Load the services array from the services file. Return True on success,
2439 ***************************************************************************/
2445 struct param_opt *data;
2449 bInGlobalSection = True;
2451 if (Globals.param_opt != NULL) {
2452 struct param_opt *next;
2453 for (data=Globals.param_opt; data; data=next) {
2455 if (data->flags & FLAG_CMDLINE) continue;
2458 DLIST_REMOVE(Globals.param_opt, data);
2465 pstrcpy(n2, lp_configfile());
2466 standard_sub_basic(n2,sizeof(n2));
2467 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2469 add_to_file_list(lp_configfile(), n2);
2471 /* We get sections first, so have to start 'behind' to make up */
2473 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2475 /* finish up the last section */
2476 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2478 if (iServiceIndex >= 0)
2479 bRetval = service_ok(iServiceIndex);
2481 lp_add_auto_services(lp_auto_services());
2483 lp_add_hidden("IPC$", "IPC");
2484 lp_add_hidden("ADMIN$", "DISK");
2488 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2489 lp_do_parameter(-1, "wins server", "127.0.0.1");
2497 /***************************************************************************
2498 Reset the max number of services.
2499 ***************************************************************************/
2501 void lp_resetnumservices(void)
2506 /***************************************************************************
2507 Return the max number of services.
2508 ***************************************************************************/
2510 int lp_numservices(void)
2512 return (iNumServices);
2515 /***************************************************************************
2516 Display the contents of the services array in human-readable form.
2517 ***************************************************************************/
2519 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2524 defaults_saved = False;
2526 dump_globals(f, show_defaults);
2528 dump_a_service(&sDefault, f);
2530 for (iService = 0; iService < maxtoprint; iService++)
2531 lp_dump_one(f, show_defaults, iService);
2534 /***************************************************************************
2535 Display the contents of one service in human-readable form.
2536 ***************************************************************************/
2538 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2541 if (ServicePtrs[snum]->szService[0] == '\0')
2543 dump_a_service(ServicePtrs[snum], f);
2547 /***************************************************************************
2548 Return the number of the service with the given name, or -1 if it doesn't
2549 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2550 getservicebyname()! This works ONLY if all services have been loaded, and
2551 does not copy the found service.
2552 ***************************************************************************/
2554 int lp_servicenumber(const char *pszServiceName)
2557 fstring serviceName;
2560 for (iService = iNumServices - 1; iService >= 0; iService--) {
2561 if (VALID(iService) && ServicePtrs[iService]->szService) {
2563 * The substitution here is used to support %U is
2566 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2567 standard_sub_basic(serviceName,sizeof(serviceName));
2568 if (strequal(serviceName, pszServiceName))
2574 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2579 int lp_find_valid_service(const char *pszServiceName)
2583 iService = lp_servicenumber(pszServiceName);
2585 if (iService >= 0 && !lp_snum_ok(iService)) {
2586 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2590 if (iService == -1) {
2591 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2597 /*******************************************************************
2598 A useful volume label function.
2599 ********************************************************************/
2600 const char *volume_label(int snum)
2602 const char *ret = lp_volume(snum);
2604 return lp_servicename(snum);
2609 /***********************************************************
2610 If we are PDC then prefer us as DMB
2611 ************************************************************/
2613 BOOL lp_domain_logons(void)
2615 return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2618 /*******************************************************************
2620 ********************************************************************/
2622 void lp_remove_service(int snum)
2624 ServicePtrs[snum]->valid = False;
2627 /*******************************************************************
2629 ********************************************************************/
2631 void lp_copy_service(int snum, const char *new_name)
2633 const char *oldname = lp_servicename(snum);
2634 do_section(new_name, NULL);
2636 snum = lp_servicenumber(new_name);
2638 lp_do_parameter(snum, "copy", oldname);
2642 const char *lp_printername(int snum)
2644 const char *ret = _lp_printername(snum);
2645 if (ret == NULL || (ret != NULL && *ret == '\0'))
2646 ret = lp_const_servicename(snum);
2652 /*******************************************************************
2653 Return the max print jobs per queue.
2654 ********************************************************************/
2656 int lp_maxprintjobs(int snum)
2658 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2659 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2660 maxjobs = PRINT_MAX_JOBID - 1;