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/svcctl.h"
63 #include "librpc/gen_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;
109 char *szWINS_CONFIG_URL;
113 char **szPasswordServers;
114 char *szSocketOptions;
116 char **szWINSservers;
118 char *szSocketAddress;
119 char *szAnnounceVersion; /* This is initialised in init_globals */
122 char **szNetbiosAliases;
123 char *szNetbiosScope;
124 char *szDomainOtherSIDs;
125 char **szNameResolveOrder;
126 char **dcerpc_ep_servers;
127 char **server_services;
128 char *ntptr_providor;
129 char *szWinbindSeparator;
130 char *szWinbinddSocketDirectory;
131 int bWinbindSealedPipes;
132 char *swat_directory;
145 int paranoid_server_security;
148 int announce_as; /* This is initialised in init_globals */
155 char *socket_options;
160 int bPreferredMaster;
161 int bEncryptPasswords;
163 int bObeyPamRestrictions;
168 int bBindInterfacesOnly;
170 int bNTStatusSupport;
176 int bClientPlaintextAuth;
177 int bClientLanManAuth;
178 int bClientNTLMv2Auth;
179 int client_use_spnego_principal;
185 struct param_opt *param_opt;
189 static global Globals;
192 * This structure describes a single service.
207 char **ntvfs_handler;
223 struct param_opt *param_opt;
225 char dummy[3]; /* for alignment */
230 /* This is a default service used to prime a services structure */
231 static service sDefault = {
233 NULL, /* szService */
236 NULL, /* szInclude */
237 NULL, /* szPrintername */
238 NULL, /* szHostsallow */
239 NULL, /* szHostsdeny */
243 NULL, /* ntvfs_handler */
244 1000, /* iMaxPrintJobs */
245 0, /* iMaxConnections */
247 True, /* bAvailable */
248 True, /* bBrowseable */
249 True, /* bRead_only */
250 False, /* bPrint_ok */
251 False, /* bMap_system */
252 False, /* bMap_hidden */
253 True, /* bMap_archive */
254 True, /* bStrictLocking */
256 False, /* bMSDfsRoot */
257 False, /* bStrictSync */
258 False, /* bCIFileSystem */
259 NULL, /* Parametric options */
264 /* local variables */
265 static service **ServicePtrs = NULL;
266 static int iNumServices = 0;
267 static int iServiceIndex = 0;
268 static BOOL bInGlobalSection = True;
269 static int default_server_announce;
271 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
273 /* prototypes for the special type handlers */
274 static BOOL handle_include(const char *pszParmValue, char **ptr);
275 static BOOL handle_copy(const char *pszParmValue, char **ptr);
277 static void set_default_server_announce_type(void);
279 static const struct enum_list enum_protocol[] = {
280 {PROTOCOL_SMB2, "SMB2"},
281 {PROTOCOL_NT1, "NT1"},
282 {PROTOCOL_LANMAN2, "LANMAN2"},
283 {PROTOCOL_LANMAN1, "LANMAN1"},
284 {PROTOCOL_CORE, "CORE"},
285 {PROTOCOL_COREPLUS, "COREPLUS"},
286 {PROTOCOL_COREPLUS, "CORE+"},
290 static const struct enum_list enum_security[] = {
291 {SEC_SHARE, "SHARE"},
296 /* Types of machine we can announce as. */
297 #define ANNOUNCE_AS_NT_SERVER 1
298 #define ANNOUNCE_AS_WIN95 2
299 #define ANNOUNCE_AS_WFW 3
300 #define ANNOUNCE_AS_NT_WORKSTATION 4
302 static const struct enum_list enum_announce_as[] = {
303 {ANNOUNCE_AS_NT_SERVER, "NT"},
304 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
305 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
306 {ANNOUNCE_AS_WIN95, "win95"},
307 {ANNOUNCE_AS_WFW, "WfW"},
311 static const struct enum_list enum_bool_auto[] = {
322 /* Client-side offline caching policy types */
323 #define CSC_POLICY_MANUAL 0
324 #define CSC_POLICY_DOCUMENTS 1
325 #define CSC_POLICY_PROGRAMS 2
326 #define CSC_POLICY_DISABLE 3
328 static const struct enum_list enum_csc_policy[] = {
329 {CSC_POLICY_MANUAL, "manual"},
330 {CSC_POLICY_DOCUMENTS, "documents"},
331 {CSC_POLICY_PROGRAMS, "programs"},
332 {CSC_POLICY_DISABLE, "disable"},
336 /* SMB signing types. */
337 static const struct enum_list enum_smb_signing_vals[] = {
338 {SMB_SIGNING_OFF, "No"},
339 {SMB_SIGNING_OFF, "False"},
340 {SMB_SIGNING_OFF, "0"},
341 {SMB_SIGNING_OFF, "Off"},
342 {SMB_SIGNING_OFF, "disabled"},
343 {SMB_SIGNING_SUPPORTED, "Yes"},
344 {SMB_SIGNING_SUPPORTED, "True"},
345 {SMB_SIGNING_SUPPORTED, "1"},
346 {SMB_SIGNING_SUPPORTED, "On"},
347 {SMB_SIGNING_SUPPORTED, "enabled"},
348 {SMB_SIGNING_REQUIRED, "required"},
349 {SMB_SIGNING_REQUIRED, "mandatory"},
350 {SMB_SIGNING_REQUIRED, "force"},
351 {SMB_SIGNING_REQUIRED, "forced"},
352 {SMB_SIGNING_REQUIRED, "enforced"},
353 {SMB_SIGNING_AUTO, "auto"},
357 static const struct enum_list enum_server_role[] = {
358 {ROLE_STANDALONE, "standalone"},
359 {ROLE_DOMAIN_MEMBER, "member server"},
360 {ROLE_DOMAIN_BDC, "bdc"},
361 {ROLE_DOMAIN_PDC, "pdc"},
366 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
368 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
369 * is implied in current control logic. This may change at some later time. A
370 * flag value of 0 means - show as development option only.
372 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
373 * screen in SWAT. This is used to exclude parameters as well as to squash all
374 * parameters that have been duplicated by pseudonyms.
376 static struct parm_struct parm_table[] = {
377 {"Base Options", P_SEP, P_SEPARATOR},
379 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
381 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
384 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
386 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
387 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
388 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
391 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
394 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
397 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
398 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
399 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
401 {"Security Options", P_SEP, P_SEPARATOR},
403 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
425 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
426 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
428 {"Logging Options", P_SEP, P_SEPARATOR},
430 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
432 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"Protocol Options", P_SEP, P_SEPARATOR},
436 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
450 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
451 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
453 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
454 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
455 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
460 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
461 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
465 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
470 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
471 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
472 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
474 {"Tuning Options", P_SEP, P_SEPARATOR},
476 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
477 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
478 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
480 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
481 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
483 {"Printing Options", P_SEP, P_SEPARATOR},
485 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
486 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
487 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
489 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
490 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
492 {"Filename Handling", P_SEP, P_SEPARATOR},
494 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
495 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
498 {"Domain Options", P_SEP, P_SEPARATOR},
500 {"Logon Options", P_SEP, P_SEPARATOR},
503 {"Browse Options", P_SEP, P_SEPARATOR},
505 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
506 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
507 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
508 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
509 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
511 {"WINS Options", P_SEP, P_SEPARATOR},
513 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
514 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
515 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
516 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
518 {"Locking Options", P_SEP, P_SEPARATOR},
520 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
522 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
524 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
526 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
527 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
528 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
530 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
532 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
536 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
538 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
539 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
541 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
542 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
543 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
545 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
548 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
549 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
550 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
551 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
553 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
558 return the parameter table
560 struct parm_struct *lp_parm_table(void)
565 /***************************************************************************
566 Initialise the global parameter structure.
567 ***************************************************************************/
568 static void init_globals(void)
573 DEBUG(3, ("Initialising global parameters\n"));
575 for (i = 0; parm_table[i].label; i++) {
576 if ((parm_table[i].type == P_STRING ||
577 parm_table[i].type == P_USTRING) &&
579 !(parm_table[i].flags & FLAG_CMDLINE)) {
580 string_set(parm_table[i].ptr, "");
584 do_parameter("config file", dyn_CONFIGFILE, NULL);
586 do_parameter("server role", "standalone", NULL);
588 /* options that can be set on the command line must be initialised via
589 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
591 do_parameter("socket options", "TCP_NODELAY", NULL);
593 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
594 myname = get_myname();
595 do_parameter("netbios name", myname, NULL);
597 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
599 do_parameter("fstype", FSTYPE_STRING, NULL);
600 do_parameter("ntvfs handler", "unixuid default", NULL);
601 do_parameter("max connections", "-1", NULL);
603 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
604 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc winbind", NULL);
605 do_parameter("ntptr providor", "simple_ldb", NULL);
606 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
607 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
608 do_parameter("sam database", "sam.ldb", NULL);
609 do_parameter("spoolss database", "spoolss.ldb", NULL);
610 do_parameter("wins config database", "wins_config.ldb", NULL);
611 do_parameter("wins database", "wins.ldb", NULL);
612 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
614 /* This hive should be dynamically generated by Samba using
615 data from the sam, but for the moment leave it in a tdb to
616 keep regedt32 from popping up an annoying dialog. */
617 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
619 /* using UTF8 by default allows us to support all chars */
620 do_parameter("unix charset", "UTF8", NULL);
622 /* Use codepage 850 as a default for the dos character set */
623 do_parameter("dos charset", "CP850", NULL);
626 * Allow the default PASSWD_CHAT to be overridden in local.h.
628 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
630 do_parameter("pid directory", dyn_PIDDIR, NULL);
631 do_parameter("lock dir", dyn_LOCKDIR, NULL);
632 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
634 do_parameter("socket address", "0.0.0.0", NULL);
635 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
637 do_parameter_var("announce version", "%d.%d",
638 DEFAULT_MAJOR_VERSION,
639 DEFAULT_MINOR_VERSION);
641 do_parameter("password server", "*", NULL);
643 do_parameter("max mux", "50", NULL);
644 do_parameter("max xmit", "12288", NULL);
645 do_parameter("password level", "0", NULL);
646 do_parameter("LargeReadwrite", "True", NULL);
647 do_parameter("min protocol", "CORE", NULL);
648 do_parameter("max protocol", "NT1", NULL);
649 do_parameter("security", "USER", NULL);
650 do_parameter("paranoid server security", "True", NULL);
651 do_parameter("EncryptPasswords", "True", NULL);
652 do_parameter("ReadRaw", "True", NULL);
653 do_parameter("WriteRaw", "True", NULL);
654 do_parameter("NullPasswords", "False", NULL);
655 do_parameter("ObeyPamRestrictions", "False", NULL);
656 do_parameter("announce as", "NT SERVER", NULL);
658 do_parameter("TimeServer", "False", NULL);
659 do_parameter("BindInterfacesOnly", "False", NULL);
660 do_parameter("Unicode", "True", NULL);
661 do_parameter("ClientLanManAuth", "True", NULL);
662 do_parameter("LanmanAuth", "True", NULL);
663 do_parameter("NTLMAuth", "True", NULL);
664 do_parameter("client use spnego principal", "False", NULL);
666 do_parameter("UnixExtensions", "False", NULL);
668 do_parameter("PreferredMaster", "Auto", NULL);
669 do_parameter("LocalMaster", "True", NULL);
671 do_parameter("wins support", "False", NULL);
672 do_parameter("dns proxy", "True", NULL);
674 do_parameter("winbind separator", "\\", NULL);
675 do_parameter("winbind sealed pipes", "True", NULL);
676 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
678 do_parameter("client signing", "Yes", NULL);
679 do_parameter("server signing", "auto", NULL);
681 do_parameter("use spnego", "True", NULL);
683 do_parameter("smb ports", SMB_PORTS, NULL);
684 do_parameter("nbt port", "137", NULL);
685 do_parameter("dgram port", "138", NULL);
686 do_parameter("cldap port", "389", NULL);
687 do_parameter("krb5 port", "88", NULL);
688 do_parameter("kpasswd port", "464", NULL);
689 do_parameter("web port", "901", NULL);
690 do_parameter("swat directory", dyn_SWATDIR, NULL);
692 do_parameter("nt status support", "True", NULL);
694 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
695 do_parameter("min wins ttl", "10", NULL);
697 do_parameter("tls enabled", "True", NULL);
698 do_parameter("tls keyfile", "tls/key.pem", NULL);
699 do_parameter("tls certfile", "tls/cert.pem", NULL);
700 do_parameter("tls cafile", "tls/ca.pem", NULL);
701 do_parameter_var("js include", "%s", dyn_JSDIR);
702 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
704 for (i = 0; parm_table[i].label; i++) {
705 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
706 parm_table[i].flags |= FLAG_DEFAULT;
711 static TALLOC_CTX *lp_talloc;
713 /******************************************************************* a
714 Free up temporary memory - called from the main loop.
715 ********************************************************************/
717 void lp_talloc_free(void)
721 talloc_free(lp_talloc);
725 /*******************************************************************
726 Convenience routine to grab string parameters into temporary memory
727 and run standard_sub_basic on them. The buffers can be written to by
728 callers without affecting the source string.
729 ********************************************************************/
731 static const char *lp_string(const char *s)
733 #if 0 /* until REWRITE done to make thread-safe */
734 size_t len = s ? strlen(s) : 0;
738 /* The follow debug is useful for tracking down memory problems
739 especially if you have an inner loop that is calling a lp_*()
740 function that returns a string. Perhaps this debug should be
741 present all the time? */
744 DEBUG(10, ("lp_string(%s)\n", s));
747 #if 0 /* until REWRITE done to make thread-safe */
749 lp_talloc = talloc_init("lp_talloc");
751 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
759 StrnCpy(ret, s, len);
761 if (trim_string(ret, "\"", "\"")) {
762 if (strchr(ret,'"') != NULL)
763 StrnCpy(ret, s, len);
766 standard_sub_basic(ret,len+100);
773 In this section all the functions that are used to access the
774 parameters from the rest of the program are defined
777 #define FN_GLOBAL_STRING(fn_name,ptr) \
778 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
779 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
780 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
781 #define FN_GLOBAL_LIST(fn_name,ptr) \
782 const char **fn_name(void) {return(*(const char ***)(ptr));}
783 #define FN_GLOBAL_BOOL(fn_name,ptr) \
784 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
785 #define FN_GLOBAL_CHAR(fn_name,ptr) \
786 char fn_name(void) {return(*(char *)(ptr));}
787 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
788 int fn_name(void) {return(*(int *)(ptr));}
790 #define FN_LOCAL_STRING(fn_name,val) \
791 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
792 #define FN_LOCAL_CONST_STRING(fn_name,val) \
793 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
794 #define FN_LOCAL_LIST(fn_name,val) \
795 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
796 #define FN_LOCAL_BOOL(fn_name,val) \
797 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
798 #define FN_LOCAL_CHAR(fn_name,val) \
799 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
800 #define FN_LOCAL_INTEGER(fn_name,val) \
801 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
803 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
804 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
805 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
806 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
807 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
808 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
809 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
810 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
811 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
812 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
813 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
814 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
815 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
816 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
817 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
818 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
819 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
820 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
821 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
822 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
823 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
824 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
825 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
826 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
827 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
828 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
829 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
830 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
834 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
835 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
839 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
840 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
845 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
846 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
847 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
849 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
851 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
852 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
853 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
854 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
855 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
856 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
857 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
858 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
859 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
860 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
861 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
862 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
863 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
864 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
865 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
866 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
867 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
868 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
869 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
870 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
872 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
873 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
874 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
876 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
877 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
878 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
879 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
880 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
881 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
882 _PUBLIC_ FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
883 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
884 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
886 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
887 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
890 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
891 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
892 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
893 static FN_LOCAL_STRING(_lp_printername, szPrintername)
894 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
895 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
896 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
897 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
898 static FN_LOCAL_STRING(lp_volume, volume)
899 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
900 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
901 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
902 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
903 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
904 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
905 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
906 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
907 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
908 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
909 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
910 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
911 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
912 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
913 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
915 /* local prototypes */
917 static int map_parameter(const char *pszParmName);
918 static int getservicebyname(const char *pszServiceName,
919 service * pserviceDest);
920 static void copy_service(service * pserviceDest,
921 service * pserviceSource, int *pcopymapDest);
922 static BOOL service_ok(int iService);
923 static BOOL do_section(const char *pszSectionName, void *);
924 static void init_copymap(service * pservice);
926 /* This is a helper function for parametrical options support. */
927 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
928 /* Actual parametrical functions are quite simple */
929 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
932 struct param_opt *data;
934 if (lookup_service >= iNumServices) return NULL;
936 data = (lookup_service < 0) ?
937 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
939 asprintf(&vfskey, "%s:%s", type, option);
943 if (strcmp(data->key, vfskey) == 0) {
950 if (lookup_service >= 0) {
951 /* Try to fetch the same option but from globals */
952 /* but only if we are not already working with Globals */
953 data = Globals.param_opt;
955 if (strcmp(data->key, vfskey) == 0) {
969 /*******************************************************************
970 convenience routine to return int parameters.
971 ********************************************************************/
972 static int lp_int(const char *s)
976 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
980 return strtol(s, NULL, 0);
983 /*******************************************************************
984 convenience routine to return unsigned long parameters.
985 ********************************************************************/
986 static int lp_ulong(const char *s)
990 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
994 return strtoul(s, NULL, 0);
997 /*******************************************************************
998 convenience routine to return boolean parameters.
999 ********************************************************************/
1000 static BOOL lp_bool(const char *s)
1005 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1009 if (!set_boolean(s, &ret)) {
1010 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1018 /* Return parametric option from a given service. Type is a part of option before ':' */
1019 /* Parametric option has following syntax: 'Type: option = value' */
1020 /* Returned value is allocated in 'lp_talloc' context */
1022 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1024 const char *value = lp_get_parametric(lookup_service, type, option);
1027 return lp_string(value);
1032 /* Return parametric option from a given service. Type is a part of option before ':' */
1033 /* Parametric option has following syntax: 'Type: option = value' */
1034 /* Returned value is allocated in 'lp_talloc' context */
1036 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1037 const char *separator)
1039 const char *value = lp_get_parametric(lookup_service, type, option);
1042 return str_list_make(talloc_autofree_context(), value, separator);
1047 /* Return parametric option from a given service. Type is a part of option before ':' */
1048 /* Parametric option has following syntax: 'Type: option = value' */
1050 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1052 const char *value = lp_get_parametric(lookup_service, type, option);
1055 return lp_int(value);
1060 /* Return parametric option from a given service. Type is a part of option before ':' */
1061 /* Parametric option has following syntax: 'Type: option = value' */
1063 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1065 const char *value = lp_get_parametric(lookup_service, type, option);
1068 return lp_ulong(value);
1073 /* Return parametric option from a given service. Type is a part of option before ':' */
1074 /* Parametric option has following syntax: 'Type: option = value' */
1076 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1078 const char *value = lp_get_parametric(lookup_service, type, option);
1081 return lp_bool(value);
1087 /***************************************************************************
1088 Initialise a service to the defaults.
1089 ***************************************************************************/
1091 static void init_service(service * pservice)
1093 memset((char *)pservice, '\0', sizeof(service));
1094 copy_service(pservice, &sDefault, NULL);
1097 /***************************************************************************
1098 Free the dynamically allocated parts of a service struct.
1099 ***************************************************************************/
1101 static void free_service(service *pservice)
1104 struct param_opt *data, *pdata;
1108 if (pservice->szService)
1109 DEBUG(5, ("free_service: Freeing service %s\n",
1110 pservice->szService));
1112 string_free(&pservice->szService);
1113 SAFE_FREE(pservice->copymap);
1115 for (i = 0; parm_table[i].label; i++) {
1116 if ((parm_table[i].type == P_STRING ||
1117 parm_table[i].type == P_USTRING) &&
1118 parm_table[i].class == P_LOCAL) {
1119 string_free((char **)
1120 (((char *)pservice) +
1121 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1122 } else if (parm_table[i].type == P_LIST &&
1123 parm_table[i].class == P_LOCAL) {
1124 char ***listp = (char ***)(((char *)pservice) +
1125 PTR_DIFF(parm_table[i].ptr, &sDefault));
1126 talloc_free(*listp);
1131 DEBUG(5,("Freeing parametrics:\n"));
1132 data = pservice->param_opt;
1134 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1135 string_free(&data->key);
1136 string_free(&data->value);
1142 ZERO_STRUCTP(pservice);
1145 /***************************************************************************
1146 Add a new service to the services array initialising it with the given
1148 ***************************************************************************/
1150 static int add_a_service(const service *pservice, const char *name)
1154 int num_to_alloc = iNumServices + 1;
1155 struct param_opt *data, *pdata;
1157 tservice = *pservice;
1159 /* it might already exist */
1161 i = getservicebyname(name, NULL);
1163 /* Clean all parametric options for service */
1164 /* They will be added during parsing again */
1165 data = ServicePtrs[i]->param_opt;
1167 string_free(&data->key);
1168 string_free(&data->value);
1173 ServicePtrs[i]->param_opt = NULL;
1178 /* find an invalid one */
1179 for (i = 0; i < iNumServices; i++)
1180 if (!ServicePtrs[i]->valid)
1183 /* if not, then create one */
1184 if (i == iNumServices) {
1187 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1190 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1195 ServicePtrs[iNumServices] = malloc_p(service);
1197 if (!ServicePtrs[iNumServices]) {
1198 DEBUG(0,("add_a_service: out of memory!\n"));
1204 free_service(ServicePtrs[i]);
1206 ServicePtrs[i]->valid = True;
1208 init_service(ServicePtrs[i]);
1209 copy_service(ServicePtrs[i], &tservice, NULL);
1211 string_set(&ServicePtrs[i]->szService, name);
1215 /***************************************************************************
1216 Add a new home service, with the specified home directory, defaults coming
1218 ***************************************************************************/
1220 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1221 const char *user, const char *pszHomedir)
1226 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1231 if (!(*(ServicePtrs[iDefaultService]->szPath))
1232 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1233 pstrcpy(newHomedir, pszHomedir);
1235 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1236 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1239 string_set(&ServicePtrs[i]->szPath, newHomedir);
1241 if (!(*(ServicePtrs[i]->comment))) {
1243 slprintf(comment, sizeof(comment) - 1,
1244 "Home directory of %s", user);
1245 string_set(&ServicePtrs[i]->comment, comment);
1247 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1248 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1250 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1256 /***************************************************************************
1257 Add a new service, based on an old one.
1258 ***************************************************************************/
1260 int lp_add_service(const char *pszService, int iDefaultService)
1262 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1265 /***************************************************************************
1266 Add the IPC service.
1267 ***************************************************************************/
1269 static BOOL lp_add_hidden(const char *name, const char *fstype)
1272 int i = add_a_service(&sDefault, name);
1277 slprintf(comment, sizeof(comment) - 1,
1278 "%s Service (%s)", fstype, Globals.szServerString);
1280 string_set(&ServicePtrs[i]->szPath, tmpdir());
1281 string_set(&ServicePtrs[i]->comment, comment);
1282 string_set(&ServicePtrs[i]->fstype, fstype);
1283 ServicePtrs[i]->iMaxConnections = -1;
1284 ServicePtrs[i]->bAvailable = True;
1285 ServicePtrs[i]->bRead_only = True;
1286 ServicePtrs[i]->bPrint_ok = False;
1287 ServicePtrs[i]->bBrowseable = False;
1289 if (strcasecmp(fstype, "IPC") == 0) {
1290 lp_do_parameter(i, "ntvfs handler", "default");
1293 DEBUG(3, ("adding hidden service %s\n", name));
1298 /***************************************************************************
1299 Add a new printer service, with defaults coming from service iFrom.
1300 ***************************************************************************/
1302 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1304 const char *comment = "From Printcap";
1305 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1310 /* note that we do NOT default the availability flag to True - */
1311 /* we take it from the default service passed. This allows all */
1312 /* dynamic printers to be disabled by disabling the [printers] */
1313 /* entry (if/when the 'available' keyword is implemented!). */
1315 /* the printer name is set to the service name. */
1316 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1317 string_set(&ServicePtrs[i]->comment, comment);
1318 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1319 /* Printers cannot be read_only. */
1320 ServicePtrs[i]->bRead_only = False;
1321 /* Printer services must be printable. */
1322 ServicePtrs[i]->bPrint_ok = True;
1324 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1326 update_server_announce_as_printserver();
1331 /***************************************************************************
1332 Map a parameter's string representation to something we can use.
1333 Returns False if the parameter string is not recognised, else TRUE.
1334 ***************************************************************************/
1336 static int map_parameter(const char *pszParmName)
1340 if (*pszParmName == '-')
1343 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1344 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1347 /* Warn only if it isn't parametric option */
1348 if (strchr(pszParmName, ':') == NULL)
1349 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1350 /* We do return 'fail' for parametric options as well because they are
1351 stored in different storage
1358 return the parameter structure for a parameter
1360 struct parm_struct *lp_parm_struct(const char *name)
1362 int parmnum = map_parameter(name);
1363 if (parmnum == -1) return NULL;
1364 return &parm_table[parmnum];
1368 return the parameter pointer for a parameter
1370 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1375 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1378 /***************************************************************************
1379 Find a service by name. Otherwise works like get_service.
1380 ***************************************************************************/
1382 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1386 for (iService = iNumServices - 1; iService >= 0; iService--)
1387 if (VALID(iService) &&
1388 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1389 if (pserviceDest != NULL)
1390 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1397 /***************************************************************************
1398 Copy a service structure to another.
1399 If pcopymapDest is NULL then copy all fields
1400 ***************************************************************************/
1402 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1405 BOOL bcopyall = (pcopymapDest == NULL);
1406 struct param_opt *data, *pdata, *paramo;
1409 for (i = 0; parm_table[i].label; i++)
1410 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1411 (bcopyall || pcopymapDest[i])) {
1412 void *def_ptr = parm_table[i].ptr;
1414 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1417 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1420 switch (parm_table[i].type) {
1422 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1427 *(int *)dest_ptr = *(int *)src_ptr;
1431 string_set(dest_ptr,
1436 string_set(dest_ptr,
1438 strupper(*(char **)dest_ptr);
1441 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1442 *(const char ***)src_ptr);
1450 init_copymap(pserviceDest);
1451 if (pserviceSource->copymap)
1452 memcpy((void *)pserviceDest->copymap,
1453 (void *)pserviceSource->copymap,
1454 sizeof(int) * NUMPARAMETERS);
1457 data = pserviceSource->param_opt;
1460 pdata = pserviceDest->param_opt;
1461 /* Traverse destination */
1463 /* If we already have same option, override it */
1464 if (strcmp(pdata->key, data->key) == 0) {
1465 string_free(&pdata->value);
1466 pdata->value = strdup(data->value);
1470 pdata = pdata->next;
1473 paramo = malloc_p(struct param_opt);
1476 paramo->key = strdup(data->key);
1477 paramo->value = strdup(data->value);
1478 DLIST_ADD(pserviceDest->param_opt, paramo);
1484 /***************************************************************************
1485 Check a service for consistency. Return False if the service is in any way
1486 incomplete or faulty, else True.
1487 ***************************************************************************/
1489 static BOOL service_ok(int iService)
1494 if (ServicePtrs[iService]->szService[0] == '\0') {
1495 DEBUG(0, ("The following message indicates an internal error:\n"));
1496 DEBUG(0, ("No service name in service entry.\n"));
1500 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1501 /* I can't see why you'd want a non-printable printer service... */
1502 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1503 if (!ServicePtrs[iService]->bPrint_ok) {
1504 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1505 ServicePtrs[iService]->szService));
1506 ServicePtrs[iService]->bPrint_ok = True;
1507 update_server_announce_as_printserver();
1509 /* [printers] service must also be non-browsable. */
1510 if (ServicePtrs[iService]->bBrowseable)
1511 ServicePtrs[iService]->bBrowseable = False;
1514 /* If a service is flagged unavailable, log the fact at level 0. */
1515 if (!ServicePtrs[iService]->bAvailable)
1516 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1517 ServicePtrs[iService]->szService));
1522 static struct file_lists {
1523 struct file_lists *next;
1527 } *file_lists = NULL;
1529 /*******************************************************************
1530 Keep a linked list of all config files so we know when one has changed
1531 it's date and needs to be reloaded.
1532 ********************************************************************/
1534 static void add_to_file_list(const char *fname, const char *subfname)
1536 struct file_lists *f = file_lists;
1539 if (f->name && !strcmp(f->name, fname))
1545 f = malloc_p(struct file_lists);
1548 f->next = file_lists;
1549 f->name = strdup(fname);
1554 f->subfname = strdup(subfname);
1560 f->modtime = file_modtime(subfname);
1562 time_t t = file_modtime(subfname);
1568 /*******************************************************************
1569 Check if a config file has changed date.
1570 ********************************************************************/
1572 BOOL lp_file_list_changed(void)
1574 struct file_lists *f = file_lists;
1575 DEBUG(6, ("lp_file_list_changed()\n"));
1581 pstrcpy(n2, f->name);
1582 standard_sub_basic(n2,sizeof(n2));
1584 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1585 f->name, n2, ctime(&f->modtime)));
1587 mod_time = file_modtime(n2);
1589 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1591 ("file %s modified: %s\n", n2,
1593 f->modtime = mod_time;
1594 SAFE_FREE(f->subfname);
1595 f->subfname = strdup(n2);
1603 /***************************************************************************
1604 Handle the include operation.
1605 ***************************************************************************/
1607 static BOOL handle_include(const char *pszParmValue, char **ptr)
1610 pstrcpy(fname, pszParmValue);
1612 standard_sub_basic(fname,sizeof(fname));
1614 add_to_file_list(pszParmValue, fname);
1616 string_set(ptr, fname);
1618 if (file_exist(fname))
1619 return (pm_process(fname, do_section, do_parameter, NULL));
1621 DEBUG(2, ("Can't find include file %s\n", fname));
1626 /***************************************************************************
1627 Handle the interpretation of the copy parameter.
1628 ***************************************************************************/
1630 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1634 service serviceTemp;
1636 string_set(ptr, pszParmValue);
1638 init_service(&serviceTemp);
1642 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1644 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1645 if (iTemp == iServiceIndex) {
1646 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1648 copy_service(ServicePtrs[iServiceIndex],
1650 ServicePtrs[iServiceIndex]->copymap);
1654 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1658 free_service(&serviceTemp);
1662 /***************************************************************************
1663 Initialise a copymap.
1664 ***************************************************************************/
1666 static void init_copymap(service * pservice)
1669 SAFE_FREE(pservice->copymap);
1670 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1671 if (!pservice->copymap)
1673 ("Couldn't allocate copymap!! (size %d)\n",
1674 (int)NUMPARAMETERS));
1676 for (i = 0; i < NUMPARAMETERS; i++)
1677 pservice->copymap[i] = True;
1680 /***************************************************************************
1681 Return the local pointer to a parameter given the service number and the
1682 pointer into the default structure.
1683 ***************************************************************************/
1685 void *lp_local_ptr(int snum, void *ptr)
1687 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1691 /***************************************************************************
1692 Process a parametric option
1693 ***************************************************************************/
1694 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1696 struct param_opt *paramo, *data;
1699 while (isspace((unsigned char)*pszParmName)) {
1703 name = strdup(pszParmName);
1704 if (!name) return False;
1709 data = Globals.param_opt;
1711 data = ServicePtrs[snum]->param_opt;
1714 /* Traverse destination */
1715 for (paramo=data; paramo; paramo=paramo->next) {
1716 /* If we already have the option set, override it unless
1717 it was a command line option and the new one isn't */
1718 if (strcmp(paramo->key, name) == 0) {
1719 if ((paramo->flags & FLAG_CMDLINE) &&
1720 !(flags & FLAG_CMDLINE)) {
1724 free(paramo->value);
1725 paramo->value = strdup(pszParmValue);
1726 paramo->flags = flags;
1732 paramo = malloc_p(struct param_opt);
1735 paramo->key = strdup(name);
1736 paramo->value = strdup(pszParmValue);
1737 paramo->flags = flags;
1739 DLIST_ADD(Globals.param_opt, paramo);
1741 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1749 /***************************************************************************
1750 Process a parameter for a particular service number. If snum < 0
1751 then assume we are in the globals.
1752 ***************************************************************************/
1753 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1756 void *parm_ptr = NULL; /* where we are going to store the result */
1757 void *def_ptr = NULL;
1759 parmnum = map_parameter(pszParmName);
1762 if (strchr(pszParmName, ':')) {
1763 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1765 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1769 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1770 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1774 /* if the flag has been set on the command line, then don't allow override,
1775 but don't report an error */
1776 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1780 def_ptr = parm_table[parmnum].ptr;
1782 /* we might point at a service, the default service or a global */
1786 if (parm_table[parmnum].class == P_GLOBAL) {
1788 ("Global parameter %s found in service section!\n",
1793 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1798 if (!ServicePtrs[snum]->copymap)
1799 init_copymap(ServicePtrs[snum]);
1801 /* this handles the aliases - set the copymap for other entries with
1802 the same data pointer */
1803 for (i = 0; parm_table[i].label; i++)
1804 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1805 ServicePtrs[snum]->copymap[i] = False;
1808 /* if it is a special case then go ahead */
1809 if (parm_table[parmnum].special) {
1810 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1814 /* now switch on the type of variable it is */
1815 switch (parm_table[parmnum].type)
1818 if (!set_boolean(pszParmValue, parm_ptr)) {
1819 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1825 *(int *)parm_ptr = atoi(pszParmValue);
1829 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1830 pszParmValue, NULL);
1834 string_set(parm_ptr, pszParmValue);
1838 string_set(parm_ptr, pszParmValue);
1839 strupper(*(char **)parm_ptr);
1843 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1846 parm_table[parmnum].enum_list[i].name)) {
1848 parm_table[parmnum].
1853 if (!parm_table[parmnum].enum_list[i].name) {
1854 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1855 pszParmValue, pszParmName));
1863 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1864 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1865 /* we have to also unset FLAG_DEFAULT on aliases */
1866 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1867 parm_table[i].flags &= ~FLAG_DEFAULT;
1869 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1870 parm_table[i].flags &= ~FLAG_DEFAULT;
1877 /***************************************************************************
1878 Process a parameter.
1879 ***************************************************************************/
1881 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1883 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1884 pszParmName, pszParmValue));
1888 variable argument do parameter
1890 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1892 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1899 s = talloc_vasprintf(NULL, fmt, ap);
1901 ret = do_parameter(pszParmName, s, NULL);
1908 set a parameter from the commandline - this is called from command line parameter
1909 parsing code. It sets the parameter then marks the parameter as unable to be modified
1910 by smb.conf processing
1912 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1914 int parmnum = map_parameter(pszParmName);
1917 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1920 if (parmnum < 0 && strchr(pszParmName, ':')) {
1921 /* set a parametric option */
1922 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1926 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1930 /* reset the CMDLINE flag in case this has been called before */
1931 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1933 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1937 parm_table[parmnum].flags |= FLAG_CMDLINE;
1939 /* we have to also set FLAG_CMDLINE on aliases */
1940 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1941 parm_table[i].flags |= FLAG_CMDLINE;
1943 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1944 parm_table[i].flags |= FLAG_CMDLINE;
1951 set a option from the commandline in 'a=b' format. Use to support --option
1953 BOOL lp_set_option(const char *option)
1971 ret = lp_set_cmdline(s, p+1);
1977 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1979 /***************************************************************************
1980 Print a parameter of the specified type.
1981 ***************************************************************************/
1983 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1989 for (i = 0; p->enum_list[i].name; i++) {
1990 if (*(int *)ptr == p->enum_list[i].value) {
1992 p->enum_list[i].name);
1999 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2003 fprintf(f, "%d", *(int *)ptr);
2007 if ((char ***)ptr && *(char ***)ptr) {
2008 char **list = *(char ***)ptr;
2010 for (; *list; list++)
2011 fprintf(f, "%s%s", *list,
2012 ((*(list+1))?", ":""));
2018 if (*(char **)ptr) {
2019 fprintf(f, "%s", *(char **)ptr);
2027 /***************************************************************************
2028 Check if two parameters are equal.
2029 ***************************************************************************/
2031 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2035 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2039 return (*((int *)ptr1) == *((int *)ptr2));
2042 return str_list_equal((const char **)(*(char ***)ptr1),
2043 (const char **)(*(char ***)ptr2));
2048 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2053 return (p1 == p2 || strequal(p1, p2));
2061 /***************************************************************************
2062 Process a new section (service). At this stage all sections are services.
2063 Later we'll have special sections that permit server parameters to be set.
2064 Returns True on success, False on failure.
2065 ***************************************************************************/
2067 static BOOL do_section(const char *pszSectionName, void *userdata)
2070 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2071 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2074 /* if we've just struck a global section, note the fact. */
2075 bInGlobalSection = isglobal;
2077 /* check for multiple global sections */
2078 if (bInGlobalSection) {
2079 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2083 /* if we have a current service, tidy it up before moving on */
2086 if (iServiceIndex >= 0)
2087 bRetval = service_ok(iServiceIndex);
2089 /* if all is still well, move to the next record in the services array */
2091 /* We put this here to avoid an odd message order if messages are */
2092 /* issued by the post-processing of a previous section. */
2093 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2095 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2097 DEBUG(0, ("Failed to add a new service\n"));
2106 /***************************************************************************
2107 Determine if a partcular base parameter is currentl set to the default value.
2108 ***************************************************************************/
2110 static BOOL is_default(int i)
2112 if (!defaults_saved)
2114 switch (parm_table[i].type) {
2116 return str_list_equal((const char **)parm_table[i].def.lvalue,
2117 (const char **)(*(char ***)parm_table[i].ptr));
2120 return strequal(parm_table[i].def.svalue,
2121 *(char **)parm_table[i].ptr);
2123 return parm_table[i].def.bvalue ==
2124 *(BOOL *)parm_table[i].ptr;
2127 return parm_table[i].def.ivalue ==
2128 *(int *)parm_table[i].ptr;
2135 /***************************************************************************
2136 Display the contents of the global structure.
2137 ***************************************************************************/
2139 static void dump_globals(FILE *f, BOOL show_defaults)
2142 struct param_opt *data;
2144 fprintf(f, "# Global parameters\n[global]\n");
2146 for (i = 0; parm_table[i].label; i++)
2147 if (parm_table[i].class == P_GLOBAL &&
2148 parm_table[i].ptr &&
2149 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2150 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2152 fprintf(f, "\t%s = ", parm_table[i].label);
2153 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2156 if (Globals.param_opt != NULL) {
2157 data = Globals.param_opt;
2159 fprintf(f, "\t%s = %s\n", data->key, data->value);
2166 /***************************************************************************
2167 Display the contents of a single services record.
2168 ***************************************************************************/
2170 static void dump_a_service(service * pService, FILE * f)
2173 struct param_opt *data;
2175 if (pService != &sDefault)
2176 fprintf(f, "\n[%s]\n", pService->szService);
2178 for (i = 0; parm_table[i].label; i++)
2179 if (parm_table[i].class == P_LOCAL &&
2180 parm_table[i].ptr &&
2181 (*parm_table[i].label != '-') &&
2182 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2183 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2185 if (pService == &sDefault) {
2186 if (defaults_saved && is_default(i))
2189 if (equal_parameter(parm_table[i].type,
2190 ((char *)pService) +
2192 ((char *)&sDefault) +
2197 fprintf(f, "\t%s = ", parm_table[i].label);
2198 print_parameter(&parm_table[i],
2199 ((char *)pService) + pdiff, f);
2202 if (pService->param_opt != NULL) {
2203 data = pService->param_opt;
2205 fprintf(f, "\t%s = %s\n", data->key, data->value);
2211 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2213 service * pService = ServicePtrs[snum];
2214 struct parm_struct *parm;
2217 parm = lp_parm_struct(parm_name);
2225 ptr = ((char *)pService) +
2226 PTR_DIFF(parm->ptr, &sDefault);
2228 print_parameter(parm,
2234 /***************************************************************************
2235 Return info about the next service in a service. snum==-1 gives the globals.
2236 Return NULL when out of parameters.
2237 ***************************************************************************/
2239 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2242 /* do the globals */
2243 for (; parm_table[*i].label; (*i)++) {
2244 if (parm_table[*i].class == P_SEPARATOR)
2245 return &parm_table[(*i)++];
2247 if (!parm_table[*i].ptr
2248 || (*parm_table[*i].label == '-'))
2252 && (parm_table[*i].ptr ==
2253 parm_table[(*i) - 1].ptr))
2256 return &parm_table[(*i)++];
2259 service *pService = ServicePtrs[snum];
2261 for (; parm_table[*i].label; (*i)++) {
2262 if (parm_table[*i].class == P_SEPARATOR)
2263 return &parm_table[(*i)++];
2265 if (parm_table[*i].class == P_LOCAL &&
2266 parm_table[*i].ptr &&
2267 (*parm_table[*i].label != '-') &&
2269 (parm_table[*i].ptr !=
2270 parm_table[(*i) - 1].ptr)))
2273 PTR_DIFF(parm_table[*i].ptr,
2276 if (allparameters ||
2277 !equal_parameter(parm_table[*i].type,
2278 ((char *)pService) +
2280 ((char *)&sDefault) +
2283 return &parm_table[(*i)++];
2293 /***************************************************************************
2294 Return TRUE if the passed service number is within range.
2295 ***************************************************************************/
2297 BOOL lp_snum_ok(int iService)
2299 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2302 /***************************************************************************
2303 Auto-load some home services.
2304 ***************************************************************************/
2306 static void lp_add_auto_services(const char *str)
2311 /***************************************************************************
2312 Announce ourselves as a print server.
2313 ***************************************************************************/
2315 void update_server_announce_as_printserver(void)
2317 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2320 /***************************************************************************
2321 Have we loaded a services file yet?
2322 ***************************************************************************/
2324 BOOL lp_loaded(void)
2329 /***************************************************************************
2330 Unload unused services.
2331 ***************************************************************************/
2333 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2336 for (i = 0; i < iNumServices; i++) {
2340 if (!snumused || !snumused(smb, i)) {
2341 ServicePtrs[i]->valid = False;
2342 free_service(ServicePtrs[i]);
2347 /***************************************************************************
2349 ***************************************************************************/
2351 void lp_killservice(int iServiceIn)
2353 if (VALID(iServiceIn)) {
2354 ServicePtrs[iServiceIn]->valid = False;
2355 free_service(ServicePtrs[iServiceIn]);
2359 /***************************************************************************
2360 Load the services array from the services file. Return True on success,
2362 ***************************************************************************/
2368 struct param_opt *data;
2372 bInGlobalSection = True;
2374 if (Globals.param_opt != NULL) {
2375 struct param_opt *next;
2376 for (data=Globals.param_opt; data; data=next) {
2378 if (data->flags & FLAG_CMDLINE) continue;
2381 DLIST_REMOVE(Globals.param_opt, data);
2388 pstrcpy(n2, lp_configfile());
2389 standard_sub_basic(n2,sizeof(n2));
2390 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2392 add_to_file_list(lp_configfile(), n2);
2394 /* We get sections first, so have to start 'behind' to make up */
2396 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2398 /* finish up the last section */
2399 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2401 if (iServiceIndex >= 0)
2402 bRetval = service_ok(iServiceIndex);
2404 lp_add_auto_services(lp_auto_services());
2406 lp_add_hidden("IPC$", "IPC");
2407 lp_add_hidden("ADMIN$", "DISK");
2409 set_default_server_announce_type();
2413 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2414 lp_do_parameter(-1, "wins server", "127.0.0.1");
2422 /***************************************************************************
2423 Reset the max number of services.
2424 ***************************************************************************/
2426 void lp_resetnumservices(void)
2431 /***************************************************************************
2432 Return the max number of services.
2433 ***************************************************************************/
2435 int lp_numservices(void)
2437 return (iNumServices);
2440 /***************************************************************************
2441 Display the contents of the services array in human-readable form.
2442 ***************************************************************************/
2444 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2449 defaults_saved = False;
2451 dump_globals(f, show_defaults);
2453 dump_a_service(&sDefault, f);
2455 for (iService = 0; iService < maxtoprint; iService++)
2456 lp_dump_one(f, show_defaults, iService);
2459 /***************************************************************************
2460 Display the contents of one service in human-readable form.
2461 ***************************************************************************/
2463 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2466 if (ServicePtrs[snum]->szService[0] == '\0')
2468 dump_a_service(ServicePtrs[snum], f);
2472 /***************************************************************************
2473 Return the number of the service with the given name, or -1 if it doesn't
2474 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2475 getservicebyname()! This works ONLY if all services have been loaded, and
2476 does not copy the found service.
2477 ***************************************************************************/
2479 int lp_servicenumber(const char *pszServiceName)
2482 fstring serviceName;
2485 for (iService = iNumServices - 1; iService >= 0; iService--) {
2486 if (VALID(iService) && ServicePtrs[iService]->szService) {
2488 * The substitution here is used to support %U is
2491 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2492 standard_sub_basic(serviceName,sizeof(serviceName));
2493 if (strequal(serviceName, pszServiceName))
2499 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2504 /*******************************************************************
2505 A useful volume label function.
2506 ********************************************************************/
2507 const char *volume_label(int snum)
2509 const char *ret = lp_volume(snum);
2511 return lp_servicename(snum);
2516 /*******************************************************************
2517 Set the server type we will announce as via nmbd.
2518 ********************************************************************/
2520 static void set_default_server_announce_type(void)
2522 default_server_announce = 0;
2523 default_server_announce |= SV_TYPE_WORKSTATION;
2524 default_server_announce |= SV_TYPE_SERVER;
2525 default_server_announce |= SV_TYPE_SERVER_UNIX;
2527 switch (lp_announce_as()) {
2528 case ANNOUNCE_AS_NT_SERVER:
2529 default_server_announce |= SV_TYPE_SERVER_NT;
2530 /* fall through... */
2531 case ANNOUNCE_AS_NT_WORKSTATION:
2532 default_server_announce |= SV_TYPE_NT;
2534 case ANNOUNCE_AS_WIN95:
2535 default_server_announce |= SV_TYPE_WIN95_PLUS;
2537 case ANNOUNCE_AS_WFW:
2538 default_server_announce |= SV_TYPE_WFW;
2544 switch (lp_server_role()) {
2545 case ROLE_DOMAIN_MEMBER:
2546 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2548 case ROLE_DOMAIN_PDC:
2549 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2551 case ROLE_DOMAIN_BDC:
2552 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2554 case ROLE_STANDALONE:
2558 if (lp_time_server())
2559 default_server_announce |= SV_TYPE_TIME_SOURCE;
2561 if (lp_host_msdfs())
2562 default_server_announce |= SV_TYPE_DFS_SERVER;
2564 /* TODO: only announce us as print server when we are a print server */
2565 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2568 /***********************************************************
2569 If we are PDC then prefer us as DMB
2570 ************************************************************/
2572 BOOL lp_domain_master(void)
2574 return (lp_server_role() == ROLE_DOMAIN_PDC);
2577 /***********************************************************
2578 If we are PDC then prefer us as DMB
2579 ************************************************************/
2581 BOOL lp_domain_logons(void)
2583 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2586 /***********************************************************
2587 If we are DMB then prefer us as LMB
2588 ************************************************************/
2590 BOOL lp_preferred_master(void)
2592 return (lp_local_master() && lp_domain_master());
2595 /*******************************************************************
2597 ********************************************************************/
2599 void lp_remove_service(int snum)
2601 ServicePtrs[snum]->valid = False;
2604 /*******************************************************************
2606 ********************************************************************/
2608 void lp_copy_service(int snum, const char *new_name)
2610 const char *oldname = lp_servicename(snum);
2611 do_section(new_name, NULL);
2613 snum = lp_servicenumber(new_name);
2615 lp_do_parameter(snum, "copy", oldname);
2620 /*******************************************************************
2621 Get the default server type we will announce as via nmbd.
2622 ********************************************************************/
2623 int lp_default_server_announce(void)
2625 return default_server_announce;
2628 const char *lp_printername(int snum)
2630 const char *ret = _lp_printername(snum);
2631 if (ret == NULL || (ret != NULL && *ret == '\0'))
2632 ret = lp_const_servicename(snum);
2638 /*******************************************************************
2639 Return the max print jobs per queue.
2640 ********************************************************************/
2642 int lp_maxprintjobs(int snum)
2644 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2645 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2646 maxjobs = PRINT_MAX_JOBID - 1;