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
58 #include "dynconfig.h"
60 #include "system/time.h"
61 #include "system/iconv.h"
62 #include "librpc/gen_ndr/ndr_svcctl.h"
63 #include "librpc/gen_ndr/ndr_samr.h"
64 #include "smb_server/smb_server.h"
65 #include "libcli/raw/signing.h"
66 #include "dlinklist.h"
67 #include "param/loadparm.h"
69 static BOOL bLoaded = False;
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;
103 char *szServerString;
104 char *szAutoServices;
110 char *szWINS_CONFIG_URL;
114 char **szPasswordServers;
115 char *szSocketOptions;
117 char **szWINSservers;
119 char *szSocketAddress;
120 char *szAnnounceVersion; /* This is initialised in init_globals */
123 char **szNetbiosAliases;
124 char *szNetbiosScope;
125 char *szDomainOtherSIDs;
126 char **szNameResolveOrder;
128 char **dcerpc_ep_servers;
129 char **server_services;
130 char *ntptr_providor;
131 char *szWinbindSeparator;
132 char *szWinbinddSocketDirectory;
133 BOOL bWinbindSealedPipes;
134 char *swat_directory;
147 BOOL paranoid_server_security;
150 int announce_as; /* This is initialised in init_globals */
157 char *socket_options;
162 BOOL bPreferredMaster;
163 BOOL bEncryptPasswords;
165 BOOL bObeyPamRestrictions;
166 BOOL bLargeReadwrite;
170 BOOL bBindInterfacesOnly;
172 BOOL bNTStatusSupport;
178 BOOL bClientPlaintextAuth;
179 BOOL bClientLanManAuth;
180 BOOL bClientNTLMv2Auth;
181 BOOL client_use_spnego_principal;
184 BOOL bUnixExtensions;
185 BOOL bDisableNetbios;
187 struct param_opt *param_opt;
191 static global Globals;
194 * This structure describes a single service.
209 char **ntvfs_handler;
225 struct param_opt *param_opt;
227 char dummy[3]; /* for alignment */
232 /* This is a default service used to prime a services structure */
233 static service sDefault = {
235 NULL, /* szService */
238 NULL, /* szInclude */
239 NULL, /* szPrintername */
240 NULL, /* szHostsallow */
241 NULL, /* szHostsdeny */
245 NULL, /* ntvfs_handler */
246 1000, /* iMaxPrintJobs */
247 0, /* iMaxConnections */
249 True, /* bAvailable */
250 True, /* bBrowseable */
251 True, /* bRead_only */
252 False, /* bPrint_ok */
253 False, /* bMap_system */
254 False, /* bMap_hidden */
255 True, /* bMap_archive */
256 True, /* bStrictLocking */
258 False, /* bMSDfsRoot */
259 False, /* bStrictSync */
260 False, /* bCIFileSystem */
261 NULL, /* Parametric options */
266 /* local variables */
267 static service **ServicePtrs = NULL;
268 static int iNumServices = 0;
269 static int iServiceIndex = 0;
270 static BOOL bInGlobalSection = True;
271 static int default_server_announce;
273 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
275 /* prototypes for the special type handlers */
276 static BOOL handle_include(const char *pszParmValue, char **ptr);
277 static BOOL handle_copy(const char *pszParmValue, char **ptr);
279 static void set_default_server_announce_type(void);
281 static const struct enum_list enum_protocol[] = {
282 {PROTOCOL_NT1, "NT1"},
283 {PROTOCOL_LANMAN2, "LANMAN2"},
284 {PROTOCOL_LANMAN1, "LANMAN1"},
285 {PROTOCOL_CORE, "CORE"},
286 {PROTOCOL_COREPLUS, "COREPLUS"},
287 {PROTOCOL_COREPLUS, "CORE+"},
291 static const struct enum_list enum_security[] = {
292 {SEC_SHARE, "SHARE"},
297 /* Types of machine we can announce as. */
298 #define ANNOUNCE_AS_NT_SERVER 1
299 #define ANNOUNCE_AS_WIN95 2
300 #define ANNOUNCE_AS_WFW 3
301 #define ANNOUNCE_AS_NT_WORKSTATION 4
303 static const struct enum_list enum_announce_as[] = {
304 {ANNOUNCE_AS_NT_SERVER, "NT"},
305 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
306 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
307 {ANNOUNCE_AS_WIN95, "win95"},
308 {ANNOUNCE_AS_WFW, "WfW"},
312 static const struct enum_list enum_bool_auto[] = {
323 /* Client-side offline caching policy types */
324 #define CSC_POLICY_MANUAL 0
325 #define CSC_POLICY_DOCUMENTS 1
326 #define CSC_POLICY_PROGRAMS 2
327 #define CSC_POLICY_DISABLE 3
329 static const struct enum_list enum_csc_policy[] = {
330 {CSC_POLICY_MANUAL, "manual"},
331 {CSC_POLICY_DOCUMENTS, "documents"},
332 {CSC_POLICY_PROGRAMS, "programs"},
333 {CSC_POLICY_DISABLE, "disable"},
337 /* SMB signing types. */
338 static const struct enum_list enum_smb_signing_vals[] = {
339 {SMB_SIGNING_OFF, "No"},
340 {SMB_SIGNING_OFF, "False"},
341 {SMB_SIGNING_OFF, "0"},
342 {SMB_SIGNING_OFF, "Off"},
343 {SMB_SIGNING_OFF, "disabled"},
344 {SMB_SIGNING_SUPPORTED, "Yes"},
345 {SMB_SIGNING_SUPPORTED, "True"},
346 {SMB_SIGNING_SUPPORTED, "1"},
347 {SMB_SIGNING_SUPPORTED, "On"},
348 {SMB_SIGNING_SUPPORTED, "enabled"},
349 {SMB_SIGNING_REQUIRED, "required"},
350 {SMB_SIGNING_REQUIRED, "mandatory"},
351 {SMB_SIGNING_REQUIRED, "force"},
352 {SMB_SIGNING_REQUIRED, "forced"},
353 {SMB_SIGNING_REQUIRED, "enforced"},
354 {SMB_SIGNING_AUTO, "auto"},
358 static const struct enum_list enum_server_role[] = {
359 {ROLE_STANDALONE, "standalone"},
360 {ROLE_DOMAIN_MEMBER, "member server"},
361 {ROLE_DOMAIN_BDC, "bdc"},
362 {ROLE_DOMAIN_PDC, "pdc"},
367 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
369 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
370 * is implied in current control logic. This may change at some later time. A
371 * flag value of 0 means - show as development option only.
373 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
374 * screen in SWAT. This is used to exclude parameters as well as to squash all
375 * parameters that have been duplicated by pseudonyms.
377 static struct parm_struct parm_table[] = {
378 {"Base Options", P_SEP, P_SEPARATOR},
380 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
382 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
384 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
387 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
388 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
389 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
391 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
394 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
395 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
398 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
399 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
400 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
402 {"Security Options", P_SEP, P_SEPARATOR},
404 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
410 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
426 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
427 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
429 {"Logging Options", P_SEP, P_SEPARATOR},
431 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
433 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"Protocol Options", P_SEP, P_SEPARATOR},
437 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
451 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"min protocol", P_ENUM, P_GLOBAL, &Globals.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_INTEGER, 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 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
531 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
532 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
537 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
539 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
540 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
542 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
543 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
544 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
546 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
549 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
550 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
551 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
552 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
554 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
559 return the parameter table
561 struct parm_struct *lp_parm_table(void)
566 /***************************************************************************
567 Initialise the global parameter structure.
568 ***************************************************************************/
569 static void init_globals(void)
574 DEBUG(3, ("Initialising global parameters\n"));
576 for (i = 0; parm_table[i].label; i++) {
577 if ((parm_table[i].type == P_STRING ||
578 parm_table[i].type == P_USTRING) &&
580 !(parm_table[i].flags & FLAG_CMDLINE)) {
581 string_set(parm_table[i].ptr, "");
585 do_parameter("config file", dyn_CONFIGFILE, NULL);
587 do_parameter("server role", "standalone", NULL);
589 /* options that can be set on the command line must be initialised via
590 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
592 do_parameter("socket options", "TCP_NODELAY", NULL);
594 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
595 myname = get_myname();
596 do_parameter("netbios name", myname, NULL);
598 do_parameter("max protocol", "NT1", NULL);
599 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
601 do_parameter("fstype", FSTYPE_STRING, NULL);
602 do_parameter("ntvfs handler", "unixuid default", NULL);
603 do_parameter("max connections", "-1", NULL);
605 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
606 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc winbind", NULL);
607 do_parameter("ntptr providor", "simple_ldb", NULL);
608 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
609 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
610 do_parameter("sam database", "sam.ldb", NULL);
611 do_parameter("spoolss database", "spoolss.ldb", NULL);
612 do_parameter("wins config database", "wins_config.ldb", NULL);
613 do_parameter("wins database", "wins.ldb", NULL);
614 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
616 /* This hive should be dynamically generated by Samba using
617 data from the sam, but for the moment leave it in a tdb to
618 keep regedt32 from popping up an annoying dialog. */
619 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
621 /* using UTF8 by default allows us to support all chars */
622 do_parameter("unix charset", "UTF8", NULL);
624 /* Use codepage 850 as a default for the dos character set */
625 do_parameter("dos charset", "CP850", NULL);
628 * Allow the default PASSWD_CHAT to be overridden in local.h.
630 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
632 do_parameter("pid directory", dyn_PIDDIR, NULL);
633 do_parameter("lock dir", dyn_LOCKDIR, NULL);
634 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
636 do_parameter("socket address", "0.0.0.0", NULL);
637 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
639 do_parameter_var("announce version", "%d.%d",
640 DEFAULT_MAJOR_VERSION,
641 DEFAULT_MINOR_VERSION);
643 do_parameter("password server", "*", NULL);
645 do_parameter("max mux", "50", NULL);
646 do_parameter("max xmit", "12288", NULL);
647 do_parameter("password level", "0", NULL);
648 do_parameter("LargeReadwrite", "True", NULL);
649 do_parameter("minprotocol", "CORE", NULL);
650 do_parameter("security", "USER", NULL);
651 do_parameter("paranoid server security", "True", NULL);
652 do_parameter("EncryptPasswords", "True", NULL);
653 do_parameter("ReadRaw", "True", NULL);
654 do_parameter("WriteRaw", "True", NULL);
655 do_parameter("NullPasswords", "False", NULL);
656 do_parameter("ObeyPamRestrictions", "False", NULL);
657 do_parameter("announce as", "NT SERVER", NULL);
659 do_parameter("TimeServer", "False", NULL);
660 do_parameter("BindInterfacesOnly", "False", NULL);
661 do_parameter("Unicode", "True", NULL);
662 do_parameter("ClientLanManAuth", "True", NULL);
663 do_parameter("LanmanAuth", "True", NULL);
664 do_parameter("NTLMAuth", "True", NULL);
665 do_parameter("client use spnego principal", "False", NULL);
667 do_parameter("UnixExtensions", "False", NULL);
669 do_parameter("PreferredMaster", "Auto", NULL);
670 do_parameter("LocalMaster", "True", NULL);
672 do_parameter("wins support", "False", NULL);
673 do_parameter("dns proxy", "True", NULL);
675 do_parameter("winbind separator", "\\", NULL);
676 do_parameter("winbind sealed pipes", "True", NULL);
677 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
679 do_parameter("client signing", "Yes", NULL);
680 do_parameter("server signing", "auto", NULL);
682 do_parameter("use spnego", "True", NULL);
684 do_parameter("smb ports", SMB_PORTS, NULL);
685 do_parameter("nbt port", "137", NULL);
686 do_parameter("dgram port", "138", NULL);
687 do_parameter("cldap port", "389", NULL);
688 do_parameter("krb5 port", "88", NULL);
689 do_parameter("kpasswd port", "464", NULL);
690 do_parameter("web port", "901", NULL);
691 do_parameter("swat directory", dyn_SWATDIR, NULL);
693 do_parameter("nt status support", "True", NULL);
695 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
696 do_parameter("min wins ttl", "10", NULL);
698 do_parameter("tls enabled", "True", NULL);
699 do_parameter("tls keyfile", "tls/key.pem", NULL);
700 do_parameter("tls certfile", "tls/cert.pem", NULL);
701 do_parameter("tls cafile", "tls/ca.pem", NULL);
702 do_parameter_var("js include", "%s", dyn_JSDIR);
703 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
705 for (i = 0; parm_table[i].label; i++) {
706 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
707 parm_table[i].flags |= FLAG_DEFAULT;
712 static TALLOC_CTX *lp_talloc;
714 /******************************************************************* a
715 Free up temporary memory - called from the main loop.
716 ********************************************************************/
718 void lp_talloc_free(void)
722 talloc_free(lp_talloc);
726 /*******************************************************************
727 Convenience routine to grab string parameters into temporary memory
728 and run standard_sub_basic on them. The buffers can be written to by
729 callers without affecting the source string.
730 ********************************************************************/
732 static const char *lp_string(const char *s)
734 #if 0 /* until REWRITE done to make thread-safe */
735 size_t len = s ? strlen(s) : 0;
739 /* The follow debug is useful for tracking down memory problems
740 especially if you have an inner loop that is calling a lp_*()
741 function that returns a string. Perhaps this debug should be
742 present all the time? */
745 DEBUG(10, ("lp_string(%s)\n", s));
748 #if 0 /* until REWRITE done to make thread-safe */
750 lp_talloc = talloc_init("lp_talloc");
752 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
760 StrnCpy(ret, s, len);
762 if (trim_string(ret, "\"", "\"")) {
763 if (strchr(ret,'"') != NULL)
764 StrnCpy(ret, s, len);
767 standard_sub_basic(ret,len+100);
774 In this section all the functions that are used to access the
775 parameters from the rest of the program are defined
778 #define FN_GLOBAL_STRING(fn_name,ptr) \
779 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
780 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
781 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
782 #define FN_GLOBAL_LIST(fn_name,ptr) \
783 const char **fn_name(void) {return(*(const char ***)(ptr));}
784 #define FN_GLOBAL_BOOL(fn_name,ptr) \
785 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
786 #define FN_GLOBAL_CHAR(fn_name,ptr) \
787 char fn_name(void) {return(*(char *)(ptr));}
788 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
789 int fn_name(void) {return(*(int *)(ptr));}
791 #define FN_LOCAL_STRING(fn_name,val) \
792 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
793 #define FN_LOCAL_CONST_STRING(fn_name,val) \
794 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
795 #define FN_LOCAL_LIST(fn_name,val) \
796 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
797 #define FN_LOCAL_BOOL(fn_name,val) \
798 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
799 #define FN_LOCAL_CHAR(fn_name,val) \
800 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
801 #define FN_LOCAL_INTEGER(fn_name,val) \
802 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
804 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
805 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
806 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
807 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
808 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
809 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
810 FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
811 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
812 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
813 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
814 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
815 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
816 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
817 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
818 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
819 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
820 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
821 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
822 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
823 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
824 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
825 FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
826 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
827 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
828 FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
829 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
830 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
831 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
832 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
833 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
834 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
835 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
836 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
837 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
838 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
839 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
840 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
841 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
842 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
843 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
844 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
845 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
846 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
847 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
848 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
849 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
850 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
851 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
852 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
854 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
855 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
856 FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
857 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
858 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
859 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
860 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
861 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
862 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
863 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
864 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
865 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
866 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
867 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
868 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
869 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
870 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
871 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
872 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
873 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
874 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
875 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
876 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
877 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
878 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
879 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
880 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
881 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
882 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
883 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
884 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
885 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
886 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
887 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
888 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
889 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
890 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
893 FN_LOCAL_STRING(lp_servicename, szService)
894 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
895 FN_LOCAL_STRING(lp_pathname, szPath)
896 static FN_LOCAL_STRING(_lp_printername, szPrintername)
897 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
898 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
899 FN_LOCAL_STRING(lp_comment, comment)
900 FN_LOCAL_STRING(lp_fstype, fstype)
901 static FN_LOCAL_STRING(lp_volume, volume)
902 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
903 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
904 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
905 FN_LOCAL_BOOL(lp_readonly, bRead_only)
906 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
907 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
908 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
909 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
910 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
911 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
912 FN_LOCAL_BOOL(lp_map_system, bMap_system)
913 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
914 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
915 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
916 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
918 /* local prototypes */
920 static int map_parameter(const char *pszParmName);
921 static int getservicebyname(const char *pszServiceName,
922 service * pserviceDest);
923 static void copy_service(service * pserviceDest,
924 service * pserviceSource, BOOL *pcopymapDest);
925 static BOOL service_ok(int iService);
926 static BOOL do_section(const char *pszSectionName, void *);
927 static void init_copymap(service * pservice);
929 /* This is a helper function for parametrical options support. */
930 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
931 /* Actual parametrical functions are quite simple */
932 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
935 struct param_opt *data;
937 if (lookup_service >= iNumServices) return NULL;
939 data = (lookup_service < 0) ?
940 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
942 asprintf(&vfskey, "%s:%s", type, option);
946 if (strcmp(data->key, vfskey) == 0) {
953 if (lookup_service >= 0) {
954 /* Try to fetch the same option but from globals */
955 /* but only if we are not already working with Globals */
956 data = Globals.param_opt;
958 if (strcmp(data->key, vfskey) == 0) {
972 /*******************************************************************
973 convenience routine to return int parameters.
974 ********************************************************************/
975 static int lp_int(const char *s)
979 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
983 return strtol(s, NULL, 0);
986 /*******************************************************************
987 convenience routine to return unsigned long parameters.
988 ********************************************************************/
989 static int lp_ulong(const char *s)
993 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
997 return strtoul(s, NULL, 0);
1000 /*******************************************************************
1001 convenience routine to return boolean parameters.
1002 ********************************************************************/
1003 static BOOL lp_bool(const char *s)
1008 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1012 if (!set_boolean(s, &ret)) {
1013 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1021 /* Return parametric option from a given service. Type is a part of option before ':' */
1022 /* Parametric option has following syntax: 'Type: option = value' */
1023 /* Returned value is allocated in 'lp_talloc' context */
1025 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1027 const char *value = lp_get_parametric(lookup_service, type, option);
1030 return lp_string(value);
1035 /* Return parametric option from a given service. Type is a part of option before ':' */
1036 /* Parametric option has following syntax: 'Type: option = value' */
1037 /* Returned value is allocated in 'lp_talloc' context */
1039 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1040 const char *separator)
1042 const char *value = lp_get_parametric(lookup_service, type, option);
1045 return str_list_make(talloc_autofree_context(), value, separator);
1050 /* Return parametric option from a given service. Type is a part of option before ':' */
1051 /* Parametric option has following syntax: 'Type: option = value' */
1053 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1055 const char *value = lp_get_parametric(lookup_service, type, option);
1058 return lp_int(value);
1063 /* Return parametric option from a given service. Type is a part of option before ':' */
1064 /* Parametric option has following syntax: 'Type: option = value' */
1066 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1068 const char *value = lp_get_parametric(lookup_service, type, option);
1071 return lp_ulong(value);
1076 /* Return parametric option from a given service. Type is a part of option before ':' */
1077 /* Parametric option has following syntax: 'Type: option = value' */
1079 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1081 const char *value = lp_get_parametric(lookup_service, type, option);
1084 return lp_bool(value);
1090 /***************************************************************************
1091 Initialise a service to the defaults.
1092 ***************************************************************************/
1094 static void init_service(service * pservice)
1096 memset((char *)pservice, '\0', sizeof(service));
1097 copy_service(pservice, &sDefault, NULL);
1100 /***************************************************************************
1101 Free the dynamically allocated parts of a service struct.
1102 ***************************************************************************/
1104 static void free_service(service *pservice)
1107 struct param_opt *data, *pdata;
1111 if (pservice->szService)
1112 DEBUG(5, ("free_service: Freeing service %s\n",
1113 pservice->szService));
1115 string_free(&pservice->szService);
1116 SAFE_FREE(pservice->copymap);
1118 for (i = 0; parm_table[i].label; i++) {
1119 if ((parm_table[i].type == P_STRING ||
1120 parm_table[i].type == P_USTRING) &&
1121 parm_table[i].class == P_LOCAL) {
1122 string_free((char **)
1123 (((char *)pservice) +
1124 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1125 } else if (parm_table[i].type == P_LIST &&
1126 parm_table[i].class == P_LOCAL) {
1127 char ***listp = (char ***)(((char *)pservice) +
1128 PTR_DIFF(parm_table[i].ptr, &sDefault));
1129 talloc_free(*listp);
1134 DEBUG(5,("Freeing parametrics:\n"));
1135 data = pservice->param_opt;
1137 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1138 string_free(&data->key);
1139 string_free(&data->value);
1145 ZERO_STRUCTP(pservice);
1148 /***************************************************************************
1149 Add a new service to the services array initialising it with the given
1151 ***************************************************************************/
1153 static int add_a_service(const service *pservice, const char *name)
1157 int num_to_alloc = iNumServices + 1;
1158 struct param_opt *data, *pdata;
1160 tservice = *pservice;
1162 /* it might already exist */
1164 i = getservicebyname(name, NULL);
1166 /* Clean all parametric options for service */
1167 /* They will be added during parsing again */
1168 data = ServicePtrs[i]->param_opt;
1170 string_free(&data->key);
1171 string_free(&data->value);
1176 ServicePtrs[i]->param_opt = NULL;
1181 /* find an invalid one */
1182 for (i = 0; i < iNumServices; i++)
1183 if (!ServicePtrs[i]->valid)
1186 /* if not, then create one */
1187 if (i == iNumServices) {
1190 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1193 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1198 ServicePtrs[iNumServices] = malloc_p(service);
1200 if (!ServicePtrs[iNumServices]) {
1201 DEBUG(0,("add_a_service: out of memory!\n"));
1207 free_service(ServicePtrs[i]);
1209 ServicePtrs[i]->valid = True;
1211 init_service(ServicePtrs[i]);
1212 copy_service(ServicePtrs[i], &tservice, NULL);
1214 string_set(&ServicePtrs[i]->szService, name);
1218 /***************************************************************************
1219 Add a new home service, with the specified home directory, defaults coming
1221 ***************************************************************************/
1223 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1224 const char *user, const char *pszHomedir)
1229 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1234 if (!(*(ServicePtrs[iDefaultService]->szPath))
1235 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1236 pstrcpy(newHomedir, pszHomedir);
1238 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1239 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1242 string_set(&ServicePtrs[i]->szPath, newHomedir);
1244 if (!(*(ServicePtrs[i]->comment))) {
1246 slprintf(comment, sizeof(comment) - 1,
1247 "Home directory of %s", user);
1248 string_set(&ServicePtrs[i]->comment, comment);
1250 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1251 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1253 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1259 /***************************************************************************
1260 Add a new service, based on an old one.
1261 ***************************************************************************/
1263 int lp_add_service(const char *pszService, int iDefaultService)
1265 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1268 /***************************************************************************
1269 Add the IPC service.
1270 ***************************************************************************/
1272 static BOOL lp_add_hidden(const char *name, const char *fstype)
1275 int i = add_a_service(&sDefault, name);
1280 slprintf(comment, sizeof(comment) - 1,
1281 "%s Service (%s)", fstype, Globals.szServerString);
1283 string_set(&ServicePtrs[i]->szPath, tmpdir());
1284 string_set(&ServicePtrs[i]->comment, comment);
1285 string_set(&ServicePtrs[i]->fstype, fstype);
1286 ServicePtrs[i]->iMaxConnections = -1;
1287 ServicePtrs[i]->bAvailable = True;
1288 ServicePtrs[i]->bRead_only = True;
1289 ServicePtrs[i]->bPrint_ok = False;
1290 ServicePtrs[i]->bBrowseable = False;
1292 if (strcasecmp(fstype, "IPC") == 0) {
1293 lp_do_parameter(i, "ntvfs handler", "default");
1296 DEBUG(3, ("adding hidden service %s\n", name));
1301 /***************************************************************************
1302 Add a new printer service, with defaults coming from service iFrom.
1303 ***************************************************************************/
1305 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1307 const char *comment = "From Printcap";
1308 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1313 /* note that we do NOT default the availability flag to True - */
1314 /* we take it from the default service passed. This allows all */
1315 /* dynamic printers to be disabled by disabling the [printers] */
1316 /* entry (if/when the 'available' keyword is implemented!). */
1318 /* the printer name is set to the service name. */
1319 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1320 string_set(&ServicePtrs[i]->comment, comment);
1321 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1322 /* Printers cannot be read_only. */
1323 ServicePtrs[i]->bRead_only = False;
1324 /* Printer services must be printable. */
1325 ServicePtrs[i]->bPrint_ok = True;
1327 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1329 update_server_announce_as_printserver();
1334 /***************************************************************************
1335 Map a parameter's string representation to something we can use.
1336 Returns False if the parameter string is not recognised, else TRUE.
1337 ***************************************************************************/
1339 static int map_parameter(const char *pszParmName)
1343 if (*pszParmName == '-')
1346 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1347 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1350 /* Warn only if it isn't parametric option */
1351 if (strchr(pszParmName, ':') == NULL)
1352 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1353 /* We do return 'fail' for parametric options as well because they are
1354 stored in different storage
1361 return the parameter structure for a parameter
1363 struct parm_struct *lp_parm_struct(const char *name)
1365 int parmnum = map_parameter(name);
1366 if (parmnum == -1) return NULL;
1367 return &parm_table[parmnum];
1371 return the parameter pointer for a parameter
1373 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1378 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1381 /***************************************************************************
1382 Find a service by name. Otherwise works like get_service.
1383 ***************************************************************************/
1385 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1389 for (iService = iNumServices - 1; iService >= 0; iService--)
1390 if (VALID(iService) &&
1391 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1392 if (pserviceDest != NULL)
1393 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1400 /***************************************************************************
1401 Copy a service structure to another.
1402 If pcopymapDest is NULL then copy all fields
1403 ***************************************************************************/
1405 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1408 BOOL bcopyall = (pcopymapDest == NULL);
1409 struct param_opt *data, *pdata, *paramo;
1412 for (i = 0; parm_table[i].label; i++)
1413 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1414 (bcopyall || pcopymapDest[i])) {
1415 void *def_ptr = parm_table[i].ptr;
1417 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1420 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1423 switch (parm_table[i].type) {
1425 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1430 *(int *)dest_ptr = *(int *)src_ptr;
1434 string_set(dest_ptr,
1439 string_set(dest_ptr,
1441 strupper(*(char **)dest_ptr);
1444 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1445 *(const char ***)src_ptr);
1453 init_copymap(pserviceDest);
1454 if (pserviceSource->copymap)
1455 memcpy((void *)pserviceDest->copymap,
1456 (void *)pserviceSource->copymap,
1457 sizeof(BOOL) * NUMPARAMETERS);
1460 data = pserviceSource->param_opt;
1463 pdata = pserviceDest->param_opt;
1464 /* Traverse destination */
1466 /* If we already have same option, override it */
1467 if (strcmp(pdata->key, data->key) == 0) {
1468 string_free(&pdata->value);
1469 pdata->value = strdup(data->value);
1473 pdata = pdata->next;
1476 paramo = malloc_p(struct param_opt);
1479 paramo->key = strdup(data->key);
1480 paramo->value = strdup(data->value);
1481 DLIST_ADD(pserviceDest->param_opt, paramo);
1487 /***************************************************************************
1488 Check a service for consistency. Return False if the service is in any way
1489 incomplete or faulty, else True.
1490 ***************************************************************************/
1492 static BOOL service_ok(int iService)
1497 if (ServicePtrs[iService]->szService[0] == '\0') {
1498 DEBUG(0, ("The following message indicates an internal error:\n"));
1499 DEBUG(0, ("No service name in service entry.\n"));
1503 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1504 /* I can't see why you'd want a non-printable printer service... */
1505 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1506 if (!ServicePtrs[iService]->bPrint_ok) {
1507 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1508 ServicePtrs[iService]->szService));
1509 ServicePtrs[iService]->bPrint_ok = True;
1510 update_server_announce_as_printserver();
1512 /* [printers] service must also be non-browsable. */
1513 if (ServicePtrs[iService]->bBrowseable)
1514 ServicePtrs[iService]->bBrowseable = False;
1517 /* If a service is flagged unavailable, log the fact at level 0. */
1518 if (!ServicePtrs[iService]->bAvailable)
1519 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1520 ServicePtrs[iService]->szService));
1525 static struct file_lists {
1526 struct file_lists *next;
1530 } *file_lists = NULL;
1532 /*******************************************************************
1533 Keep a linked list of all config files so we know when one has changed
1534 it's date and needs to be reloaded.
1535 ********************************************************************/
1537 static void add_to_file_list(const char *fname, const char *subfname)
1539 struct file_lists *f = file_lists;
1542 if (f->name && !strcmp(f->name, fname))
1548 f = malloc_p(struct file_lists);
1551 f->next = file_lists;
1552 f->name = strdup(fname);
1557 f->subfname = strdup(subfname);
1563 f->modtime = file_modtime(subfname);
1565 time_t t = file_modtime(subfname);
1571 /*******************************************************************
1572 Check if a config file has changed date.
1573 ********************************************************************/
1575 BOOL lp_file_list_changed(void)
1577 struct file_lists *f = file_lists;
1578 DEBUG(6, ("lp_file_list_changed()\n"));
1584 pstrcpy(n2, f->name);
1585 standard_sub_basic(n2,sizeof(n2));
1587 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1588 f->name, n2, ctime(&f->modtime)));
1590 mod_time = file_modtime(n2);
1592 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1594 ("file %s modified: %s\n", n2,
1596 f->modtime = mod_time;
1597 SAFE_FREE(f->subfname);
1598 f->subfname = strdup(n2);
1606 /***************************************************************************
1607 Handle the include operation.
1608 ***************************************************************************/
1610 static BOOL handle_include(const char *pszParmValue, char **ptr)
1613 pstrcpy(fname, pszParmValue);
1615 standard_sub_basic(fname,sizeof(fname));
1617 add_to_file_list(pszParmValue, fname);
1619 string_set(ptr, fname);
1621 if (file_exist(fname))
1622 return (pm_process(fname, do_section, do_parameter, NULL));
1624 DEBUG(2, ("Can't find include file %s\n", fname));
1629 /***************************************************************************
1630 Handle the interpretation of the copy parameter.
1631 ***************************************************************************/
1633 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1637 service serviceTemp;
1639 string_set(ptr, pszParmValue);
1641 init_service(&serviceTemp);
1645 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1647 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1648 if (iTemp == iServiceIndex) {
1649 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1651 copy_service(ServicePtrs[iServiceIndex],
1653 ServicePtrs[iServiceIndex]->copymap);
1657 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1661 free_service(&serviceTemp);
1665 /***************************************************************************
1666 Initialise a copymap.
1667 ***************************************************************************/
1669 static void init_copymap(service * pservice)
1672 SAFE_FREE(pservice->copymap);
1673 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1674 if (!pservice->copymap)
1676 ("Couldn't allocate copymap!! (size %d)\n",
1677 (int)NUMPARAMETERS));
1679 for (i = 0; i < NUMPARAMETERS; i++)
1680 pservice->copymap[i] = True;
1683 /***************************************************************************
1684 Return the local pointer to a parameter given the service number and the
1685 pointer into the default structure.
1686 ***************************************************************************/
1688 void *lp_local_ptr(int snum, void *ptr)
1690 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1694 /***************************************************************************
1695 Process a parametric option
1696 ***************************************************************************/
1697 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1699 struct param_opt *paramo, *data;
1702 while (isspace((unsigned char)*pszParmName)) {
1706 name = strdup(pszParmName);
1707 if (!name) return False;
1712 data = Globals.param_opt;
1714 data = ServicePtrs[snum]->param_opt;
1717 /* Traverse destination */
1718 for (paramo=data; paramo; paramo=paramo->next) {
1719 /* If we already have the option set, override it unless
1720 it was a command line option and the new one isn't */
1721 if (strcmp(paramo->key, name) == 0) {
1722 if ((paramo->flags & FLAG_CMDLINE) &&
1723 !(flags & FLAG_CMDLINE)) {
1727 free(paramo->value);
1728 paramo->value = strdup(pszParmValue);
1729 paramo->flags = flags;
1735 paramo = malloc_p(struct param_opt);
1738 paramo->key = strdup(name);
1739 paramo->value = strdup(pszParmValue);
1740 paramo->flags = flags;
1742 DLIST_ADD(Globals.param_opt, paramo);
1744 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1752 /***************************************************************************
1753 Process a parameter for a particular service number. If snum < 0
1754 then assume we are in the globals.
1755 ***************************************************************************/
1756 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1759 void *parm_ptr = NULL; /* where we are going to store the result */
1760 void *def_ptr = NULL;
1762 parmnum = map_parameter(pszParmName);
1765 if (strchr(pszParmName, ':')) {
1766 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1768 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1772 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1773 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1777 /* if the flag has been set on the command line, then don't allow override,
1778 but don't report an error */
1779 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1783 def_ptr = parm_table[parmnum].ptr;
1785 /* we might point at a service, the default service or a global */
1789 if (parm_table[parmnum].class == P_GLOBAL) {
1791 ("Global parameter %s found in service section!\n",
1796 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1801 if (!ServicePtrs[snum]->copymap)
1802 init_copymap(ServicePtrs[snum]);
1804 /* this handles the aliases - set the copymap for other entries with
1805 the same data pointer */
1806 for (i = 0; parm_table[i].label; i++)
1807 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1808 ServicePtrs[snum]->copymap[i] = False;
1811 /* if it is a special case then go ahead */
1812 if (parm_table[parmnum].special) {
1813 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1817 /* now switch on the type of variable it is */
1818 switch (parm_table[parmnum].type)
1821 if (!set_boolean(pszParmValue, parm_ptr)) {
1822 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1828 *(int *)parm_ptr = atoi(pszParmValue);
1832 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1833 pszParmValue, NULL);
1837 string_set(parm_ptr, pszParmValue);
1841 string_set(parm_ptr, pszParmValue);
1842 strupper(*(char **)parm_ptr);
1846 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1849 parm_table[parmnum].enum_list[i].name)) {
1851 parm_table[parmnum].
1856 if (!parm_table[parmnum].enum_list[i].name) {
1857 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1858 pszParmValue, pszParmName));
1866 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1867 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1868 /* we have to also unset FLAG_DEFAULT on aliases */
1869 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1870 parm_table[i].flags &= ~FLAG_DEFAULT;
1872 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1873 parm_table[i].flags &= ~FLAG_DEFAULT;
1880 /***************************************************************************
1881 Process a parameter.
1882 ***************************************************************************/
1884 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1886 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1887 pszParmName, pszParmValue));
1891 variable argument do parameter
1893 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1895 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1902 s = talloc_vasprintf(NULL, fmt, ap);
1904 ret = do_parameter(pszParmName, s, NULL);
1911 set a parameter from the commandline - this is called from command line parameter
1912 parsing code. It sets the parameter then marks the parameter as unable to be modified
1913 by smb.conf processing
1915 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1917 int parmnum = map_parameter(pszParmName);
1920 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1923 if (parmnum < 0 && strchr(pszParmName, ':')) {
1924 /* set a parametric option */
1925 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1929 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1933 /* reset the CMDLINE flag in case this has been called before */
1934 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1936 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1940 parm_table[parmnum].flags |= FLAG_CMDLINE;
1942 /* we have to also set FLAG_CMDLINE on aliases */
1943 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1944 parm_table[i].flags |= FLAG_CMDLINE;
1946 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1947 parm_table[i].flags |= FLAG_CMDLINE;
1954 set a option from the commandline in 'a=b' format. Use to support --option
1956 BOOL lp_set_option(const char *option)
1974 ret = lp_set_cmdline(s, p+1);
1980 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1982 /***************************************************************************
1983 Print a parameter of the specified type.
1984 ***************************************************************************/
1986 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1992 for (i = 0; p->enum_list[i].name; i++) {
1993 if (*(int *)ptr == p->enum_list[i].value) {
1995 p->enum_list[i].name);
2002 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2006 fprintf(f, "%d", *(int *)ptr);
2010 if ((char ***)ptr && *(char ***)ptr) {
2011 char **list = *(char ***)ptr;
2013 for (; *list; list++)
2014 fprintf(f, "%s%s", *list,
2015 ((*(list+1))?", ":""));
2021 if (*(char **)ptr) {
2022 fprintf(f, "%s", *(char **)ptr);
2030 /***************************************************************************
2031 Check if two parameters are equal.
2032 ***************************************************************************/
2034 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2038 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2042 return (*((int *)ptr1) == *((int *)ptr2));
2045 return str_list_equal((const char **)(*(char ***)ptr1),
2046 (const char **)(*(char ***)ptr2));
2051 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2056 return (p1 == p2 || strequal(p1, p2));
2064 /***************************************************************************
2065 Process a new section (service). At this stage all sections are services.
2066 Later we'll have special sections that permit server parameters to be set.
2067 Returns True on success, False on failure.
2068 ***************************************************************************/
2070 static BOOL do_section(const char *pszSectionName, void *userdata)
2073 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2074 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2077 /* if we've just struck a global section, note the fact. */
2078 bInGlobalSection = isglobal;
2080 /* check for multiple global sections */
2081 if (bInGlobalSection) {
2082 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2086 /* if we have a current service, tidy it up before moving on */
2089 if (iServiceIndex >= 0)
2090 bRetval = service_ok(iServiceIndex);
2092 /* if all is still well, move to the next record in the services array */
2094 /* We put this here to avoid an odd message order if messages are */
2095 /* issued by the post-processing of a previous section. */
2096 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2098 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2100 DEBUG(0, ("Failed to add a new service\n"));
2109 /***************************************************************************
2110 Determine if a partcular base parameter is currentl set to the default value.
2111 ***************************************************************************/
2113 static BOOL is_default(int i)
2115 if (!defaults_saved)
2117 switch (parm_table[i].type) {
2119 return str_list_equal((const char **)parm_table[i].def.lvalue,
2120 (const char **)(*(char ***)parm_table[i].ptr));
2123 return strequal(parm_table[i].def.svalue,
2124 *(char **)parm_table[i].ptr);
2126 return parm_table[i].def.bvalue ==
2127 *(BOOL *)parm_table[i].ptr;
2130 return parm_table[i].def.ivalue ==
2131 *(int *)parm_table[i].ptr;
2138 /***************************************************************************
2139 Display the contents of the global structure.
2140 ***************************************************************************/
2142 static void dump_globals(FILE *f, BOOL show_defaults)
2145 struct param_opt *data;
2147 fprintf(f, "# Global parameters\n[global]\n");
2149 for (i = 0; parm_table[i].label; i++)
2150 if (parm_table[i].class == P_GLOBAL &&
2151 parm_table[i].ptr &&
2152 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2153 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2155 fprintf(f, "\t%s = ", parm_table[i].label);
2156 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2159 if (Globals.param_opt != NULL) {
2160 data = Globals.param_opt;
2162 fprintf(f, "\t%s = %s\n", data->key, data->value);
2169 /***************************************************************************
2170 Display the contents of a single services record.
2171 ***************************************************************************/
2173 static void dump_a_service(service * pService, FILE * f)
2176 struct param_opt *data;
2178 if (pService != &sDefault)
2179 fprintf(f, "\n[%s]\n", pService->szService);
2181 for (i = 0; parm_table[i].label; i++)
2182 if (parm_table[i].class == P_LOCAL &&
2183 parm_table[i].ptr &&
2184 (*parm_table[i].label != '-') &&
2185 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2186 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2188 if (pService == &sDefault) {
2189 if (defaults_saved && is_default(i))
2192 if (equal_parameter(parm_table[i].type,
2193 ((char *)pService) +
2195 ((char *)&sDefault) +
2200 fprintf(f, "\t%s = ", parm_table[i].label);
2201 print_parameter(&parm_table[i],
2202 ((char *)pService) + pdiff, f);
2205 if (pService->param_opt != NULL) {
2206 data = pService->param_opt;
2208 fprintf(f, "\t%s = %s\n", data->key, data->value);
2214 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2216 service * pService = ServicePtrs[snum];
2219 struct parm_struct *parm;
2227 parm = lp_parm_struct(parm_name);
2235 ptr = ((char *)pService) +
2236 PTR_DIFF(parm->ptr, &sDefault);
2238 print_parameter(parm,
2244 /***************************************************************************
2245 Return info about the next service in a service. snum==-1 gives the globals.
2246 Return NULL when out of parameters.
2247 ***************************************************************************/
2249 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2252 /* do the globals */
2253 for (; parm_table[*i].label; (*i)++) {
2254 if (parm_table[*i].class == P_SEPARATOR)
2255 return &parm_table[(*i)++];
2257 if (!parm_table[*i].ptr
2258 || (*parm_table[*i].label == '-'))
2262 && (parm_table[*i].ptr ==
2263 parm_table[(*i) - 1].ptr))
2266 return &parm_table[(*i)++];
2269 service *pService = ServicePtrs[snum];
2271 for (; parm_table[*i].label; (*i)++) {
2272 if (parm_table[*i].class == P_SEPARATOR)
2273 return &parm_table[(*i)++];
2275 if (parm_table[*i].class == P_LOCAL &&
2276 parm_table[*i].ptr &&
2277 (*parm_table[*i].label != '-') &&
2279 (parm_table[*i].ptr !=
2280 parm_table[(*i) - 1].ptr)))
2283 PTR_DIFF(parm_table[*i].ptr,
2286 if (allparameters ||
2287 !equal_parameter(parm_table[*i].type,
2288 ((char *)pService) +
2290 ((char *)&sDefault) +
2293 return &parm_table[(*i)++];
2303 /***************************************************************************
2304 Return TRUE if the passed service number is within range.
2305 ***************************************************************************/
2307 BOOL lp_snum_ok(int iService)
2309 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2312 /***************************************************************************
2313 Auto-load some home services.
2314 ***************************************************************************/
2316 static void lp_add_auto_services(const char *str)
2321 /***************************************************************************
2322 Announce ourselves as a print server.
2323 ***************************************************************************/
2325 void update_server_announce_as_printserver(void)
2327 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2330 /***************************************************************************
2331 Have we loaded a services file yet?
2332 ***************************************************************************/
2334 BOOL lp_loaded(void)
2339 /***************************************************************************
2340 Unload unused services.
2341 ***************************************************************************/
2343 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2346 for (i = 0; i < iNumServices; i++) {
2350 if (!snumused || !snumused(smb, i)) {
2351 ServicePtrs[i]->valid = False;
2352 free_service(ServicePtrs[i]);
2357 /***************************************************************************
2359 ***************************************************************************/
2361 void lp_killservice(int iServiceIn)
2363 if (VALID(iServiceIn)) {
2364 ServicePtrs[iServiceIn]->valid = False;
2365 free_service(ServicePtrs[iServiceIn]);
2369 /***************************************************************************
2370 Load the services array from the services file. Return True on success,
2372 ***************************************************************************/
2378 struct param_opt *data;
2382 bInGlobalSection = True;
2384 if (Globals.param_opt != NULL) {
2385 struct param_opt *next;
2386 for (data=Globals.param_opt; data; data=next) {
2388 if (data->flags & FLAG_CMDLINE) continue;
2391 DLIST_REMOVE(Globals.param_opt, data);
2398 pstrcpy(n2, lp_configfile());
2399 standard_sub_basic(n2,sizeof(n2));
2400 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2402 add_to_file_list(lp_configfile(), n2);
2404 /* We get sections first, so have to start 'behind' to make up */
2406 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2408 /* finish up the last section */
2409 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2411 if (iServiceIndex >= 0)
2412 bRetval = service_ok(iServiceIndex);
2414 lp_add_auto_services(lp_auto_services());
2416 lp_add_hidden("IPC$", "IPC");
2417 lp_add_hidden("ADMIN$", "DISK");
2419 set_default_server_announce_type();
2423 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2424 lp_do_parameter(-1, "wins server", "127.0.0.1");
2432 /***************************************************************************
2433 Reset the max number of services.
2434 ***************************************************************************/
2436 void lp_resetnumservices(void)
2441 /***************************************************************************
2442 Return the max number of services.
2443 ***************************************************************************/
2445 int lp_numservices(void)
2447 return (iNumServices);
2450 /***************************************************************************
2451 Display the contents of the services array in human-readable form.
2452 ***************************************************************************/
2454 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2459 defaults_saved = False;
2461 dump_globals(f, show_defaults);
2463 dump_a_service(&sDefault, f);
2465 for (iService = 0; iService < maxtoprint; iService++)
2466 lp_dump_one(f, show_defaults, iService);
2469 /***************************************************************************
2470 Display the contents of one service in human-readable form.
2471 ***************************************************************************/
2473 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2476 if (ServicePtrs[snum]->szService[0] == '\0')
2478 dump_a_service(ServicePtrs[snum], f);
2482 /***************************************************************************
2483 Return the number of the service with the given name, or -1 if it doesn't
2484 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2485 getservicebyname()! This works ONLY if all services have been loaded, and
2486 does not copy the found service.
2487 ***************************************************************************/
2489 int lp_servicenumber(const char *pszServiceName)
2492 fstring serviceName;
2495 for (iService = iNumServices - 1; iService >= 0; iService--) {
2496 if (VALID(iService) && ServicePtrs[iService]->szService) {
2498 * The substitution here is used to support %U is
2501 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2502 standard_sub_basic(serviceName,sizeof(serviceName));
2503 if (strequal(serviceName, pszServiceName))
2509 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2514 /*******************************************************************
2515 A useful volume label function.
2516 ********************************************************************/
2517 const char *volume_label(int snum)
2519 const char *ret = lp_volume(snum);
2521 return lp_servicename(snum);
2526 /*******************************************************************
2527 Set the server type we will announce as via nmbd.
2528 ********************************************************************/
2530 static void set_default_server_announce_type(void)
2532 default_server_announce = 0;
2533 default_server_announce |= SV_TYPE_WORKSTATION;
2534 default_server_announce |= SV_TYPE_SERVER;
2535 default_server_announce |= SV_TYPE_SERVER_UNIX;
2537 switch (lp_announce_as()) {
2538 case ANNOUNCE_AS_NT_SERVER:
2539 default_server_announce |= SV_TYPE_SERVER_NT;
2540 /* fall through... */
2541 case ANNOUNCE_AS_NT_WORKSTATION:
2542 default_server_announce |= SV_TYPE_NT;
2544 case ANNOUNCE_AS_WIN95:
2545 default_server_announce |= SV_TYPE_WIN95_PLUS;
2547 case ANNOUNCE_AS_WFW:
2548 default_server_announce |= SV_TYPE_WFW;
2554 switch (lp_server_role()) {
2555 case ROLE_DOMAIN_MEMBER:
2556 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2558 case ROLE_DOMAIN_PDC:
2559 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2561 case ROLE_DOMAIN_BDC:
2562 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2564 case ROLE_STANDALONE:
2568 if (lp_time_server())
2569 default_server_announce |= SV_TYPE_TIME_SOURCE;
2571 if (lp_host_msdfs())
2572 default_server_announce |= SV_TYPE_DFS_SERVER;
2574 /* TODO: only announce us as print server when we are a print server */
2575 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2578 /***********************************************************
2579 If we are PDC then prefer us as DMB
2580 ************************************************************/
2582 BOOL lp_domain_master(void)
2584 return (lp_server_role() == ROLE_DOMAIN_PDC);
2587 /***********************************************************
2588 If we are PDC then prefer us as DMB
2589 ************************************************************/
2591 BOOL lp_domain_logons(void)
2593 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2596 /***********************************************************
2597 If we are DMB then prefer us as LMB
2598 ************************************************************/
2600 BOOL lp_preferred_master(void)
2602 return (lp_local_master() && lp_domain_master());
2605 /*******************************************************************
2607 ********************************************************************/
2609 void lp_remove_service(int snum)
2611 ServicePtrs[snum]->valid = False;
2614 /*******************************************************************
2616 ********************************************************************/
2618 void lp_copy_service(int snum, const char *new_name)
2620 const char *oldname = lp_servicename(snum);
2621 do_section(new_name, NULL);
2623 snum = lp_servicenumber(new_name);
2625 lp_do_parameter(snum, "copy", oldname);
2630 /*******************************************************************
2631 Get the default server type we will announce as via nmbd.
2632 ********************************************************************/
2633 int lp_default_server_announce(void)
2635 return default_server_announce;
2638 const char *lp_printername(int snum)
2640 const char *ret = _lp_printername(snum);
2641 if (ret == NULL || (ret != NULL && *ret == '\0'))
2642 ret = lp_const_servicename(snum);
2648 /*******************************************************************
2649 Return the max print jobs per queue.
2650 ********************************************************************/
2652 int lp_maxprintjobs(int snum)
2654 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2655 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2656 maxjobs = PRINT_MAX_JOBID - 1;