1/* 2 * Copyright (c) 1997-2014 Erez Zadok 3 * Copyright (c) 1990 Jan-Simon Pendry 4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry at Imperial College, London. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * 36 * File: am-utils/amd/conf.c 37 * 38 */ 39 40/* 41 * Functions to handle the configuration file. 42 */ 43 44#ifdef HAVE_CONFIG_H 45# include <config.h> 46#endif /* HAVE_CONFIG_H */ 47#include <am_defs.h> 48#include <amd.h> 49 50 51/* 52 * MACROS: 53 */ 54/* Turn on to show some info about maps being configured */ 55/* #define DEBUG_CONF */ 56 57/* 58 * TYPEDEFS: 59 */ 60typedef int (*OptFuncPtr)(const char *); 61 62/* 63 * STRUCTURES: 64 */ 65struct _func_map { 66 char *name; 67 OptFuncPtr func; 68}; 69 70/* 71 * FORWARD DECLARATIONS: 72 */ 73static int gopt_arch(const char *val); 74static int gopt_auto_attrcache(const char *val); 75static int gopt_auto_dir(const char *val); 76static int gopt_auto_nfs_version(const char *val); 77static int gopt_autofs_use_lofs(const char *val); 78static int gopt_browsable_dirs(const char *val); 79static int gopt_cache_duration(const char *val); 80static int gopt_cluster(const char *val); 81static int gopt_debug_mtab_file(const char *val); 82static int gopt_debug_options(const char *val); 83static int gopt_dismount_interval(const char *val); 84static int gopt_domain_strip(const char *val); 85static int gopt_exec_map_timeout(const char *val); 86static int gopt_forced_unmounts(const char *val); 87static int gopt_full_os(const char *val); 88static int gopt_fully_qualified_hosts(const char *val); 89static int gopt_hesiod_base(const char *val); 90static int gopt_karch(const char *val); 91static int gopt_ldap_base(const char *val); 92static int gopt_ldap_cache_maxmem(const char *val); 93static int gopt_ldap_cache_seconds(const char *val); 94static int gopt_ldap_hostports(const char *val); 95static int gopt_ldap_proto_version(const char *val); 96static int gopt_local_domain(const char *val); 97static int gopt_localhost_address(const char *val); 98static int gopt_log_file(const char *val); 99static int gopt_log_options(const char *val); 100static int gopt_map_defaults(const char *val); 101static int gopt_map_options(const char *val); 102static int gopt_map_reload_interval(const char *val); 103static int gopt_map_type(const char *val); 104static int gopt_mount_type(const char *val); 105static int gopt_pid_file(const char *val); 106static int gopt_portmap_program(const char *val); 107static int gopt_preferred_amq_port(const char *val); 108static int gopt_nfs_allow_any_interface(const char *val); 109static int gopt_nfs_allow_insecure_port(const char *val); 110static int gopt_nfs_proto(const char *val); 111static int gopt_nfs_retransmit_counter(const char *val); 112static int gopt_nfs_retransmit_counter_udp(const char *val); 113static int gopt_nfs_retransmit_counter_tcp(const char *val); 114static int gopt_nfs_retransmit_counter_toplvl(const char *val); 115static int gopt_nfs_retry_interval(const char *val); 116static int gopt_nfs_retry_interval_udp(const char *val); 117static int gopt_nfs_retry_interval_tcp(const char *val); 118static int gopt_nfs_retry_interval_toplvl(const char *val); 119static int gopt_nfs_vers(const char *val); 120static int gopt_nfs_vers_ping(const char *val); 121static int gopt_nis_domain(const char *val); 122static int gopt_normalize_hostnames(const char *val); 123static int gopt_normalize_slashes(const char *val); 124static int gopt_os(const char *val); 125static int gopt_osver(const char *val); 126static int gopt_plock(const char *val); 127static int gopt_print_pid(const char *val); 128static int gopt_print_version(const char *val); 129static int gopt_restart_mounts(const char *val); 130static int gopt_search_path(const char *val); 131static int gopt_selectors_in_defaults(const char *val); 132static int gopt_show_statfs_entries(const char *val); 133static int gopt_sun_map_syntax(const char *val); 134static int gopt_truncate_log(const char *val); 135static int gopt_unmount_on_exit(const char *val); 136static int gopt_use_tcpwrappers(const char *val); 137static int gopt_vendor(const char *val); 138static int process_global_option(const char *key, const char *val); 139static int process_one_regular_map(const cf_map_t *cfm); 140static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm); 141static int ropt_browsable_dirs(const char *val, cf_map_t *cfm); 142static int ropt_map_name(const char *val, cf_map_t *cfm); 143static int ropt_map_defaults(const char *val, cf_map_t *cfm); 144static int ropt_map_options(const char *val, cf_map_t *cfm); 145static int ropt_map_type(const char *val, cf_map_t *cfm); 146static int ropt_mount_type(const char *val, cf_map_t *cfm); 147static int ropt_search_path(const char *val, cf_map_t *cfm); 148static int ropt_sun_map_syntax(const char *val, cf_map_t *cfm); 149static int ropt_tag(const char *val, cf_map_t *cfm); 150static void init_cf_map(cf_map_t *cfm); 151 152 153/* 154 * STATIC VARIABLES: 155 */ 156static cf_map_t *head_map, *cur_map; 157 158static struct _func_map glob_functable[] = { 159 {"arch", gopt_arch}, 160 {"auto_attrcache", gopt_auto_attrcache}, 161 {"auto_dir", gopt_auto_dir}, 162 {"auto_nfs_version", gopt_auto_nfs_version}, 163 {"autofs_use_lofs", gopt_autofs_use_lofs}, 164 {"browsable_dirs", gopt_browsable_dirs}, 165 {"cache_duration", gopt_cache_duration}, 166 {"cluster", gopt_cluster}, 167 {"debug_mtab_file", gopt_debug_mtab_file}, 168 {"debug_options", gopt_debug_options}, 169 {"dismount_interval", gopt_dismount_interval}, 170 {"domain_strip", gopt_domain_strip}, 171 {"exec_map_timeout", gopt_exec_map_timeout}, 172 {"forced_unmounts", gopt_forced_unmounts}, 173 {"fully_qualified_hosts", gopt_fully_qualified_hosts}, 174 {"full_os", gopt_full_os}, 175 {"hesiod_base", gopt_hesiod_base}, 176 {"karch", gopt_karch}, 177 {"ldap_base", gopt_ldap_base}, 178 {"ldap_cache_maxmem", gopt_ldap_cache_maxmem}, 179 {"ldap_cache_seconds", gopt_ldap_cache_seconds}, 180 {"ldap_hostports", gopt_ldap_hostports}, 181 {"ldap_proto_version", gopt_ldap_proto_version}, 182 {"local_domain", gopt_local_domain}, 183 {"localhost_address", gopt_localhost_address}, 184 {"log_file", gopt_log_file}, 185 {"log_options", gopt_log_options}, 186 {"map_defaults", gopt_map_defaults}, 187 {"map_options", gopt_map_options}, 188 {"map_reload_interval", gopt_map_reload_interval}, 189 {"map_type", gopt_map_type}, 190 {"mount_type", gopt_mount_type}, 191 {"pid_file", gopt_pid_file}, 192 {"portmap_program", gopt_portmap_program}, 193 {"preferred_amq_port", gopt_preferred_amq_port}, 194 {"nfs_allow_any_interface", gopt_nfs_allow_any_interface}, 195 {"nfs_allow_insecure_port", gopt_nfs_allow_insecure_port}, 196 {"nfs_proto", gopt_nfs_proto}, 197 {"nfs_retransmit_counter", gopt_nfs_retransmit_counter}, 198 {"nfs_retransmit_counter_udp", gopt_nfs_retransmit_counter_udp}, 199 {"nfs_retransmit_counter_tcp", gopt_nfs_retransmit_counter_tcp}, 200 {"nfs_retransmit_counter_toplvl", gopt_nfs_retransmit_counter_toplvl}, 201 {"nfs_retry_interval", gopt_nfs_retry_interval}, 202 {"nfs_retry_interval_udp", gopt_nfs_retry_interval_udp}, 203 {"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp}, 204 {"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl}, 205 {"nfs_vers", gopt_nfs_vers}, 206 {"nfs_vers_ping", gopt_nfs_vers_ping}, 207 {"nis_domain", gopt_nis_domain}, 208 {"normalize_hostnames", gopt_normalize_hostnames}, 209 {"normalize_slashes", gopt_normalize_slashes}, 210 {"os", gopt_os}, 211 {"osver", gopt_osver}, 212 {"plock", gopt_plock}, 213 {"print_pid", gopt_print_pid}, 214 {"print_version", gopt_print_version}, 215 {"restart_mounts", gopt_restart_mounts}, 216 {"search_path", gopt_search_path}, 217 {"selectors_on_default", gopt_selectors_in_defaults}, 218 {"selectors_in_defaults", gopt_selectors_in_defaults}, 219 {"show_statfs_entries", gopt_show_statfs_entries}, 220 {"sun_map_syntax", gopt_sun_map_syntax}, 221 {"truncate_log", gopt_truncate_log}, 222 {"unmount_on_exit", gopt_unmount_on_exit}, 223 {"use_tcpwrappers", gopt_use_tcpwrappers}, 224 {"vendor", gopt_vendor}, 225 {NULL, NULL} 226}; 227 228 229/* 230 * Initialize a map from [global] defaults. 231 */ 232static void 233init_cf_map(cf_map_t *cfm) 234{ 235 if (!cfm) 236 return; 237 238 /* 239 * Initialize a regular map's flags and other variables from the 240 * global ones, so that they are applied to all maps. Of course, each map 241 * can then override the flags individually. 242 * 243 * NOTES: 244 * (1): Will only work for maps that appear after [global]. 245 * (2): I'm assigning pointers directly from the global map. 246 */ 247 248 /* initialize map_type from [global] */ 249 cfm->cfm_type = gopt.map_type; 250 251 /* initialize map_defaults from [global] */ 252 cfm->cfm_defaults = gopt.map_defaults; 253 254 /* initialize map_opts from [global] */ 255 cfm->cfm_opts = gopt.map_options; 256 257 /* initialize search_path from [global] */ 258 cfm->cfm_search_path = gopt.search_path; 259 260 /* 261 * Initialize flags that are common both to [global] and a local map 262 * (that is, they could be inherited from the global section). 263 */ 264 cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS | 265 CFM_BROWSABLE_DIRS_FULL | 266 CFM_MOUNT_TYPE_AUTOFS | 267 CFM_SELECTORS_IN_DEFAULTS | 268 CFM_SUN_MAP_SYNTAX ); 269} 270 271 272/* 273 * Process configuration file options (called from YACC parser). 274 * Return 0 if OK, 1 otherwise. 275 */ 276int 277set_conf_kv(const char *section, const char *key, const char *val) 278{ 279 int ret; 280 281#ifdef DEBUG_CONF 282 fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n", 283 section, key, val); 284#endif /* DEBUG_CONF */ 285 286 /* 287 * If global section, process kv pairs one at a time. 288 */ 289 if (STREQ(section, "global")) { 290 /* 291 * Check if a regular map was configured before "global", 292 * and warn about it. 293 */ 294 if (cur_map && cur_map->cfm_dir) { 295 static short printed_this_error; 296 if (!printed_this_error) { 297 fprintf(stderr, "found regular map \"%s\" before global one.\n", 298 cur_map->cfm_dir); 299 printed_this_error = 1; 300 } 301 } 302 303 /* process the global option first */ 304 ret = process_global_option(key, val); 305 306 /* return status from the processing of the global option */ 307 return ret; 308 } 309 310 /* 311 * Otherwise we found a non-global option: store it after some testing. 312 */ 313 314 /* initialize (static) global list head and current map pointer */ 315 if (!head_map && !cur_map) { 316 cur_map = CALLOC(cf_map_t); 317 if (!cur_map) { 318 perror("calloc"); 319 exit(1); 320 } 321 /* initialize first head map from global defaults */ 322 init_cf_map(cur_map); 323 head_map = cur_map; 324 } 325 326 /* check if we found a new map, then allocate and initialize it */ 327 if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) { 328 /* allocate new map struct */ 329 cf_map_t *tmp_map = CALLOC(cf_map_t); 330 if (!tmp_map) { 331 perror("calloc"); 332 exit(1); 333 } 334 /* initialize it from global defaults */ 335 init_cf_map(tmp_map); 336 /* append it to end of linked list */ 337 cur_map->cfm_next = tmp_map; 338 cur_map = tmp_map; 339 } 340 341 /* now process a single entry of a regular map */ 342 return process_regular_option(section, key, val, cur_map); 343} 344 345 346/* 347 * Process global section of configuration file options. 348 * Return 0 upon success, 1 otherwise. 349 */ 350static int 351process_global_option(const char *key, const char *val) 352{ 353 struct _func_map *gfp; 354 355 /* ensure that val is valid */ 356 if (!val || val[0] == '\0') 357 return 1; 358 359 /* 360 * search for global function. 361 */ 362 for (gfp = glob_functable; gfp->name; gfp++) 363 if (FSTREQ(gfp->name, key)) 364 return (gfp->func)(val); 365 366 fprintf(stderr, "conf: unknown global key: \"%s\"\n", key); 367 return 1; /* failed to match any command */ 368} 369 370 371static int 372gopt_arch(const char *val) 373{ 374 gopt.arch = xstrdup(val); 375 return 0; 376} 377 378 379static int 380gopt_auto_attrcache(const char *val) 381{ 382 gopt.auto_attrcache = atoi(val); 383 if (gopt.auto_attrcache < 0) { 384 fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val); 385 return 1; 386 } 387 return 0; 388} 389 390 391static int 392gopt_auto_dir(const char *val) 393{ 394 gopt.auto_dir = xstrdup(val); 395 return 0; 396} 397 398static int 399gopt_auto_nfs_version(const char *val) 400{ 401 if (strcmp(val, "2") == 0) 402 nfs_dispatcher = nfs_program_2; 403 else if (strcmp(val, "3") == 0) 404 nfs_dispatcher = nfs_program_3; 405 else { 406 fprintf(stderr, "conf: bad auto nfs version : \"%s\"\n", val); 407 return 1; 408 } 409 return 0; 410} 411 412static int 413gopt_autofs_use_lofs(const char *val) 414{ 415 if (STREQ(val, "yes")) { 416 gopt.flags |= CFM_AUTOFS_USE_LOFS; 417 return 0; 418 } else if (STREQ(val, "no")) { 419 gopt.flags &= ~CFM_AUTOFS_USE_LOFS; 420 return 0; 421 } 422 423 fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val); 424 return 1; /* unknown value */ 425} 426 427 428static int 429gopt_browsable_dirs(const char *val) 430{ 431 if (STREQ(val, "full")) { 432 gopt.flags |= CFM_BROWSABLE_DIRS_FULL; 433 return 0; 434 } else if (STREQ(val, "yes")) { 435 gopt.flags |= CFM_BROWSABLE_DIRS; 436 return 0; 437 } else if (STREQ(val, "no")) { 438 gopt.flags &= ~CFM_BROWSABLE_DIRS; 439 return 0; 440 } 441 442 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); 443 return 1; /* unknown value */ 444} 445 446 447static int 448gopt_cache_duration(const char *val) 449{ 450 gopt.am_timeo = atoi(val); 451 if (gopt.am_timeo <= 0) 452 gopt.am_timeo = AM_TTL; 453 return 0; 454} 455 456 457static int 458gopt_cluster(const char *val) 459{ 460 gopt.cluster = xstrdup(val); 461 return 0; 462} 463 464 465static int 466gopt_debug_mtab_file(const char *val) 467{ 468 gopt.debug_mtab_file = xstrdup(val); 469 return 0; 470} 471 472 473static int 474gopt_debug_options(const char *val) 475{ 476#ifdef DEBUG 477 usage += debug_option((char *)val); 478 return 0; 479#else /* not DEBUG */ 480 fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", 481 am_get_progname()); 482 return 1; 483#endif /* not DEBUG */ 484} 485 486 487static int 488gopt_dismount_interval(const char *val) 489{ 490 gopt.am_timeo_w = atoi(val); 491 if (gopt.am_timeo_w <= 0) 492 gopt.am_timeo_w = AM_TTL_W; 493 return 0; 494} 495 496 497static int 498gopt_domain_strip(const char *val) 499{ 500 if (STREQ(val, "yes")) { 501 gopt.flags |= CFM_DOMAIN_STRIP; 502 return 0; 503 } else if (STREQ(val, "no")) { 504 gopt.flags &= ~CFM_DOMAIN_STRIP; 505 return 0; 506 } 507 508 fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val); 509 return 1; /* unknown value */ 510} 511 512 513static int 514gopt_exec_map_timeout(const char *val) 515{ 516 gopt.exec_map_timeout = atoi(val); 517 if (gopt.exec_map_timeout <= 0) 518 gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */ 519 return 0; 520} 521 522 523static int 524gopt_forced_unmounts(const char *val) 525{ 526 if (STREQ(val, "yes")) { 527#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE) 528 fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n"); 529 return 1; 530#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */ 531# ifdef __linux__ 532 /* 533 * HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten 534 * stable until 2.4. And it had MNT_DETACH since 2.4, but it hasn't 535 * gotten stable since 2.6. So alert users if they're trying to use a 536 * feature that may not work well on their older kernel. 537 */ 538 { 539 struct utsname un; 540 if (uname(&un) >= 0) { 541# ifdef MNT2_GEN_OPT_FORCE 542 if (strcmp(un.release, "2.4.0") < 0) 543 fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n"); 544# endif /* MNT2_GEN_OPT_FORCE */ 545# ifdef MNT2_GEN_OPT_DETACH 546 if (strcmp(un.release, "2.6.0") < 0) 547 fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n"); 548# endif /* MNT2_GEN_OPT_DETACH */ 549 } 550 } 551# endif /* __linux__ */ 552 gopt.flags |= CFM_FORCED_UNMOUNTS; 553 return 0; 554#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */ 555 } else if (STREQ(val, "no")) { 556 gopt.flags &= ~CFM_FORCED_UNMOUNTS; 557 return 0; 558 } 559 560 fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val); 561 return 1; /* unknown value */ 562} 563 564 565static int 566gopt_full_os(const char *val) 567{ 568 gopt.op_sys_full = xstrdup(val); 569 return 0; 570} 571 572 573static int 574gopt_fully_qualified_hosts(const char *val) 575{ 576 if (STREQ(val, "yes")) { 577 gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS; 578 return 0; 579 } else if (STREQ(val, "no")) { 580 gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS; 581 return 0; 582 } 583 584 fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val); 585 return 1; /* unknown value */ 586} 587 588 589static int 590gopt_hesiod_base(const char *val) 591{ 592#ifdef HAVE_MAP_HESIOD 593 gopt.hesiod_base = xstrdup(val); 594 return 0; 595#else /* not HAVE_MAP_HESIOD */ 596 fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n"); 597 return 1; 598#endif /* not HAVE_MAP_HESIOD */ 599} 600 601 602static int 603gopt_karch(const char *val) 604{ 605 gopt.karch = xstrdup(val); 606 return 0; 607} 608 609 610static int 611gopt_pid_file(const char *val) 612{ 613 gopt.pid_file = xstrdup(val); 614 return 0; 615} 616 617 618static int 619gopt_local_domain(const char *val) 620{ 621 gopt.sub_domain = xstrdup(val); 622 return 0; 623} 624 625 626static int 627gopt_localhost_address(const char *val) 628{ 629 gopt.localhost_address = xstrdup(val); 630 return 0; 631} 632 633 634static int 635gopt_ldap_base(const char *val) 636{ 637#ifdef HAVE_MAP_LDAP 638 gopt.ldap_base = xstrdup(val); 639 return 0; 640#else /* not HAVE_MAP_LDAP */ 641 fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n"); 642 return 1; 643#endif /* not HAVE_MAP_LDAP */ 644} 645 646 647static int 648gopt_ldap_cache_seconds(const char *val) 649{ 650#ifdef HAVE_MAP_LDAP 651 char *end; 652 653 gopt.ldap_cache_seconds = strtol((char *)val, &end, 10); 654 if (end == val) { 655 fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val); 656 return 1; 657 } 658 return 0; 659#else /* not HAVE_MAP_LDAP */ 660 fprintf(stderr, "conf: ldap_cache_seconds option ignored. No LDAP support available.\n"); 661 return 1; 662#endif /* not HAVE_MAP_LDAP */ 663} 664 665 666static int 667gopt_ldap_cache_maxmem(const char *val) 668{ 669#ifdef HAVE_MAP_LDAP 670 char *end; 671 672 gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10); 673 if (end == val) { 674 fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val); 675 return 1; 676 } 677 return 0; 678#else /* not HAVE_MAP_LDAP */ 679 fprintf(stderr, "conf: ldap_cache_maxmem option ignored. No LDAP support available.\n"); 680 return 1; 681#endif /* not HAVE_MAP_LDAP */ 682} 683 684 685static int 686gopt_ldap_hostports(const char *val) 687{ 688#ifdef HAVE_MAP_LDAP 689 gopt.ldap_hostports = xstrdup(val); 690 return 0; 691#else /* not HAVE_MAP_LDAP */ 692 fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n"); 693 return 1; 694#endif /* not HAVE_MAP_LDAP */ 695 696} 697 698 699static int 700gopt_ldap_proto_version(const char *val) 701{ 702#ifdef HAVE_MAP_LDAP 703 char *end; 704 705 gopt.ldap_proto_version = strtol((char *)val, &end, 10); 706 if (end == val) { 707 fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val); 708 return 1; 709 } 710 711 if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) { 712 fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val); 713 return 1; 714 } 715 switch (gopt.ldap_proto_version) { 716 /* XXX: what about LDAP_VERSION1? */ 717 case LDAP_VERSION2: 718#ifdef LDAP_VERSION3 719 case LDAP_VERSION3: 720#endif /* LDAP_VERSION3 */ 721#ifdef LDAP_VERSION4 722 case LDAP_VERSION4: 723#endif /* LDAP_VERSION4 */ 724 break; 725 default: 726 fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val); 727 return 1; 728 } 729 return 0; 730#else /* not HAVE_MAP_LDAP */ 731 fprintf(stderr, "conf: ldap_proto_version option ignored. No LDAP support available.\n"); 732 return 1; 733#endif /* not HAVE_MAP_LDAP */ 734} 735 736 737static int 738gopt_log_file(const char *val) 739{ 740 gopt.logfile = xstrdup(val); 741 return 0; 742} 743 744 745static int 746gopt_log_options(const char *val) 747{ 748 usage += switch_option((char *)val); 749 return 0; 750} 751 752 753static int 754gopt_map_defaults(const char *val) 755{ 756 gopt.map_defaults = xstrdup(val); 757 return 0; 758} 759 760 761static int 762gopt_map_options(const char *val) 763{ 764 gopt.map_options = xstrdup(val); 765 return 0; 766} 767 768 769static int 770gopt_map_reload_interval(const char *val) 771{ 772 gopt.map_reload_interval = atoi(val); 773 if (gopt.map_reload_interval <= 0) 774 gopt.map_reload_interval = ONE_HOUR; 775 return 0; 776} 777 778 779static int 780gopt_map_type(const char *val) 781{ 782 /* check if map type exist */ 783 if (!mapc_type_exists(val)) { 784 fprintf(stderr, "conf: no such map type \"%s\"\n", val); 785 return 1; 786 } 787 gopt.map_type = xstrdup(val); 788 return 0; 789} 790 791 792static int 793gopt_mount_type(const char *val) 794{ 795 if (STREQ(val, "autofs")) { 796#ifdef HAVE_FS_AUTOFS 797 gopt.flags |= CFM_MOUNT_TYPE_AUTOFS; 798 amd_use_autofs++; 799 return 0; 800#else /* not HAVE_FS_AUTOFS */ 801 fprintf(stderr, "conf: no autofs support available\n"); 802 return 1; 803#endif /* not HAVE_FS_AUTOFS */ 804 } else if (STREQ(val, "nfs")) { 805 gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS; 806 return 0; 807 } 808 809 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); 810 return 1; /* unknown value */ 811} 812 813 814static int 815gopt_portmap_program(const char *val) 816{ 817 gopt.portmap_program = atol(val); 818 /* 819 * allow alternate program numbers to be no more than 10 offset from 820 * official amd program number (300019). 821 */ 822 if (gopt.portmap_program < AMQ_PROGRAM || 823 gopt.portmap_program > AMQ_PROGRAM + 10) { 824 gopt.portmap_program = AMQ_PROGRAM; 825 set_amd_program_number(gopt.portmap_program); 826 fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val); 827 return 1; 828 } 829 830 set_amd_program_number(gopt.portmap_program); 831 return 0; /* all is OK */ 832} 833 834 835static int 836gopt_preferred_amq_port(const char *val) 837{ 838 gopt.preferred_amq_port = atoi(val); 839 840 /* 841 * No need to check value: preferred_amq_port is an unsigned short and 0 842 * is a valid number, meaning "any port". 843 */ 844 return 0; /* all is OK */ 845} 846 847 848static int 849gopt_nfs_allow_any_interface(const char *val) 850{ 851 if (STREQ(val, "yes")) { 852 gopt.flags |= CFM_NFS_ANY_INTERFACE; 853 return 0; 854 } else if (STREQ(val, "no")) { 855 gopt.flags &= ~CFM_NFS_ANY_INTERFACE; 856 return 0; 857 } 858 859 fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val); 860 return 1; /* unknown value */ 861} 862 863 864static int 865gopt_nfs_allow_insecure_port(const char *val) 866{ 867 if (STREQ(val, "yes")) { 868 gopt.flags |= CFM_NFS_INSECURE_PORT; 869 return 0; 870 } else if (STREQ(val, "no")) { 871 gopt.flags &= ~CFM_NFS_INSECURE_PORT; 872 return 0; 873 } 874 875 fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val); 876 return 1; /* unknown value */ 877} 878 879 880static int 881gopt_nfs_proto(const char *val) 882{ 883 if (STREQ(val, "udp") || STREQ(val, "tcp")) { 884 gopt.nfs_proto = xstrdup(val); 885 return 0; 886 } 887 fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val); 888 return 1; 889} 890 891 892static int 893gopt_nfs_retransmit_counter(const char *val) 894{ 895 int i; 896 897 for (i=0; i<AMU_TYPE_MAX; ++i) 898 gopt.amfs_auto_retrans[i] = atoi(val); 899 return 0; 900} 901 902 903static int 904gopt_nfs_retransmit_counter_udp(const char *val) 905{ 906 gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val); 907 return 0; 908} 909 910 911static int 912gopt_nfs_retransmit_counter_tcp(const char *val) 913{ 914 gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val); 915 return 0; 916} 917 918 919static int 920gopt_nfs_retransmit_counter_toplvl(const char *val) 921{ 922 gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val); 923 return 0; 924} 925 926 927static int 928gopt_nfs_retry_interval(const char *val) 929{ 930 int i; 931 932 for (i=0; i<AMU_TYPE_MAX; ++i) 933 gopt.amfs_auto_timeo[i] = atoi(val); 934 return 0; 935} 936 937 938static int 939gopt_nfs_retry_interval_udp(const char *val) 940{ 941 gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val); 942 return 0; 943} 944 945 946static int 947gopt_nfs_retry_interval_tcp(const char *val) 948{ 949 gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val); 950 return 0; 951} 952 953 954static int 955gopt_nfs_retry_interval_toplvl(const char *val) 956{ 957 gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val); 958 return 0; 959} 960 961 962static int 963gopt_nfs_vers(const char *val) 964{ 965 int i = atoi(val); 966 967 if (i == 2 || i == 3 || i == 4) { 968 gopt.nfs_vers = i; 969 return 0; 970 } 971 fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val); 972 return 1; 973} 974 975 976static int 977gopt_nfs_vers_ping(const char *val) 978{ 979 int i = atoi(val); 980 981 if (i == 2 || i == 3 || i == 4) { 982 gopt.nfs_vers_ping = i; 983 return 0; 984 } 985 fprintf(stderr, "conf: illegal nfs_vers_ping \"%s\"\n", val); 986 return 1; 987} 988 989static int 990gopt_nis_domain(const char *val) 991{ 992#ifdef HAVE_MAP_NIS 993 gopt.nis_domain = xstrdup(val); 994 return 0; 995#else /* not HAVE_MAP_NIS */ 996 fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n"); 997 return 1; 998#endif /* not HAVE_MAP_NIS */ 999} 1000 1001 1002static int 1003gopt_normalize_hostnames(const char *val) 1004{ 1005 if (STREQ(val, "yes")) { 1006 gopt.flags |= CFM_NORMALIZE_HOSTNAMES; 1007 return 0; 1008 } else if (STREQ(val, "no")) { 1009 gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES; 1010 return 0; 1011 } 1012 1013 fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val); 1014 return 1; /* unknown value */ 1015} 1016 1017 1018static int 1019gopt_normalize_slashes(const char *val) 1020{ 1021 if (STREQ(val, "yes")) { 1022 gopt.flags |= CFM_NORMALIZE_SLASHES; 1023 return 0; 1024 } else if (STREQ(val, "no")) { 1025 gopt.flags &= ~CFM_NORMALIZE_SLASHES; 1026 return 0; 1027 } 1028 1029 fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val); 1030 return 1; /* unknown value */ 1031} 1032 1033 1034static int 1035gopt_os(const char *val) 1036{ 1037 gopt.op_sys = xstrdup(val); 1038 return 0; 1039} 1040 1041 1042static int 1043gopt_osver(const char *val) 1044{ 1045 gopt.op_sys_ver = xstrdup(val); 1046 return 0; 1047} 1048 1049 1050static int 1051gopt_plock(const char *val) 1052{ 1053 if (STREQ(val, "yes")) { 1054 gopt.flags |= CFM_PROCESS_LOCK; 1055 return 0; 1056 } else if (STREQ(val, "no")) { 1057 gopt.flags &= ~CFM_PROCESS_LOCK; 1058 return 0; 1059 } 1060 1061 fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val); 1062 return 1; /* unknown value */ 1063} 1064 1065 1066static int 1067gopt_print_pid(const char *val) 1068{ 1069 if (STREQ(val, "yes")) { 1070 gopt.flags |= CFM_PRINT_PID; 1071 return 0; 1072 } else if (STREQ(val, "no")) { 1073 gopt.flags &= ~CFM_PRINT_PID; 1074 return 0; 1075 } 1076 1077 fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val); 1078 return 1; /* unknown value */ 1079} 1080 1081 1082static int 1083gopt_print_version(const char *val) 1084{ 1085 if (STREQ(val, "yes")) { 1086 char *vers = get_version_string(); 1087 fputs(vers, stderr); 1088 XFREE(vers); 1089 return 0; 1090 } else if (STREQ(val, "no")) { 1091 return 0; 1092 } 1093 1094 fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val); 1095 return 1; /* unknown value */ 1096} 1097 1098 1099static int 1100gopt_restart_mounts(const char *val) 1101{ 1102 if (STREQ(val, "yes")) { 1103 gopt.flags |= CFM_RESTART_EXISTING_MOUNTS; 1104 return 0; 1105 } else if (STREQ(val, "no")) { 1106 gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS; 1107 return 0; 1108 } 1109 1110 fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val); 1111 return 1; /* unknown value */ 1112} 1113 1114 1115static int 1116gopt_search_path(const char *val) 1117{ 1118 gopt.search_path = xstrdup(val); 1119 return 0; 1120} 1121 1122 1123static int 1124gopt_selectors_in_defaults(const char *val) 1125{ 1126 if (STREQ(val, "yes")) { 1127 gopt.flags |= CFM_SELECTORS_IN_DEFAULTS; 1128 return 0; 1129 } else if (STREQ(val, "no")) { 1130 gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS; 1131 return 0; 1132 } 1133 1134 fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val); 1135 return 1; /* unknown value */ 1136} 1137 1138 1139static int 1140gopt_show_statfs_entries(const char *val) 1141{ 1142 if (STREQ(val, "yes")) { 1143 gopt.flags |= CFM_SHOW_STATFS_ENTRIES; 1144 return 0; 1145 } else if (STREQ(val, "no")) { 1146 gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES; 1147 return 0; 1148 } 1149 1150 fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val); 1151 return 1; /* unknown value */ 1152} 1153 1154 1155static int 1156gopt_sun_map_syntax(const char *val) 1157{ 1158 if (STREQ(val, "yes")) { 1159 gopt.flags |= CFM_SUN_MAP_SYNTAX; 1160 return 0; 1161 } else if (STREQ(val, "no")) { 1162 gopt.flags &= ~CFM_SUN_MAP_SYNTAX; 1163 return 0; 1164 } 1165 1166 fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val); 1167 return 1; /* unknown value */ 1168} 1169 1170 1171static int 1172gopt_truncate_log(const char *val) 1173{ 1174 if (STREQ(val, "yes")) { 1175 gopt.flags |= CFM_TRUNCATE_LOG; 1176 return 0; 1177 } else if (STREQ(val, "no")) { 1178 gopt.flags &= ~CFM_TRUNCATE_LOG; 1179 return 0; 1180 } 1181 1182 fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val); 1183 return 1; /* unknown value */ 1184} 1185 1186 1187static int 1188gopt_unmount_on_exit(const char *val) 1189{ 1190 if (STREQ(val, "yes")) { 1191 gopt.flags |= CFM_UNMOUNT_ON_EXIT; 1192 return 0; 1193 } else if (STREQ(val, "no")) { 1194 gopt.flags &= ~CFM_UNMOUNT_ON_EXIT; 1195 return 0; 1196 } 1197 1198 fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val); 1199 return 1; /* unknown value */ 1200} 1201 1202 1203static int 1204gopt_use_tcpwrappers(const char *val) 1205{ 1206#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) 1207 if (STREQ(val, "yes")) { 1208 gopt.flags |= CFM_USE_TCPWRAPPERS; 1209 return 0; 1210 } else if (STREQ(val, "no")) { 1211 gopt.flags &= ~CFM_USE_TCPWRAPPERS; 1212 return 0; 1213 } 1214#else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ 1215 fprintf(stderr, "conf: no tcpd/libwrap support available\n"); 1216 return 1; 1217#endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ 1218 1219 fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val); 1220 return 1; /* unknown value */ 1221} 1222 1223 1224static int 1225gopt_vendor(const char *val) 1226{ 1227 gopt.op_sys_vendor = xstrdup(val); 1228 return 0; 1229} 1230 1231 1232/* 1233 * Collect one entry for a regular map 1234 */ 1235static int 1236process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm) 1237{ 1238 /* ensure that val is valid */ 1239 if (!section || section[0] == '\0' || 1240 !key || key[0] == '\0' || 1241 !val || val[0] == '\0' || 1242 !cfm) { 1243 fprintf(stderr, "conf: process_regular_option: null entries\n"); 1244 return 1; 1245 } 1246 1247 /* check if initializing a new map */ 1248 if (!cfm->cfm_dir) 1249 cfm->cfm_dir = xstrdup(section); 1250 1251 /* check for each possible field */ 1252 if (STREQ(key, "browsable_dirs")) 1253 return ropt_browsable_dirs(val, cfm); 1254 1255 if (STREQ(key, "map_name")) 1256 return ropt_map_name(val, cfm); 1257 1258 if (STREQ(key, "map_defaults")) 1259 return ropt_map_defaults(val, cfm); 1260 1261 if (STREQ(key, "map_options")) 1262 return ropt_map_options(val, cfm); 1263 1264 if (STREQ(key, "map_type")) 1265 return ropt_map_type(val, cfm); 1266 1267 if (STREQ(key, "mount_type")) 1268 return ropt_mount_type(val, cfm); 1269 1270 if (STREQ(key, "search_path")) 1271 return ropt_search_path(val, cfm); 1272 1273 if (STREQ(key, "sun_map_syntax")) 1274 return ropt_sun_map_syntax(val, cfm); 1275 1276 if (STREQ(key, "tag")) 1277 return ropt_tag(val, cfm); 1278 1279 fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n", 1280 key, section); 1281 return 1; /* failed to match any command */ 1282} 1283 1284 1285static int 1286ropt_browsable_dirs(const char *val, cf_map_t *cfm) 1287{ 1288 if (STREQ(val, "full")) { 1289 cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL; 1290 return 0; 1291 } else if (STREQ(val, "yes")) { 1292 cfm->cfm_flags |= CFM_BROWSABLE_DIRS; 1293 return 0; 1294 } else if (STREQ(val, "no")) { 1295 cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS; 1296 return 0; 1297 } 1298 1299 fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); 1300 return 1; /* unknown value */ 1301} 1302 1303 1304static int 1305ropt_map_name(const char *val, cf_map_t *cfm) 1306{ 1307 cfm->cfm_name = xstrdup(val); 1308 return 0; 1309} 1310 1311 1312static int 1313ropt_map_defaults(const char *val, cf_map_t *cfm) 1314{ 1315 cfm->cfm_defaults = xstrdup(val); 1316 return 0; 1317} 1318 1319 1320static int 1321ropt_map_options(const char *val, cf_map_t *cfm) 1322{ 1323 cfm->cfm_opts = xstrdup(val); 1324 return 0; 1325} 1326 1327 1328static int 1329ropt_map_type(const char *val, cf_map_t *cfm) 1330{ 1331 /* check if map type exist */ 1332 if (!mapc_type_exists(val)) { 1333 fprintf(stderr, "conf: no such map type \"%s\"\n", val); 1334 return 1; 1335 } 1336 cfm->cfm_type = xstrdup(val); 1337 return 0; 1338} 1339 1340 1341static int 1342ropt_mount_type(const char *val, cf_map_t *cfm) 1343{ 1344 if (STREQ(val, "autofs")) { 1345#ifdef HAVE_FS_AUTOFS 1346 cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS; 1347 amd_use_autofs++; 1348 return 0; 1349#else /* not HAVE_FS_AUTOFS */ 1350 fprintf(stderr, "conf: no autofs support available\n"); 1351 return 1; 1352#endif /* not HAVE_FS_AUTOFS */ 1353 } else if (STREQ(val, "nfs")) { 1354 cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS; 1355 return 0; 1356 } 1357 1358 fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); 1359 return 1; /* unknown value */ 1360} 1361 1362 1363static int 1364ropt_search_path(const char *val, cf_map_t *cfm) 1365{ 1366 cfm->cfm_search_path = xstrdup(val); 1367 return 0; 1368} 1369 1370 1371static int 1372ropt_sun_map_syntax(const char *val, cf_map_t *cfm) 1373{ 1374 if (STREQ(val, "yes")) { 1375 cfm->cfm_flags |= CFM_SUN_MAP_SYNTAX; 1376 return 0; 1377 1378 } else if (STREQ(val, "no")) { 1379 cfm->cfm_flags &= ~CFM_SUN_MAP_SYNTAX; 1380 return 0; 1381 } 1382 1383 fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val); 1384 return 1; /* unknown value */ 1385} 1386 1387 1388static int 1389ropt_tag(const char *val, cf_map_t *cfm) 1390{ 1391 cfm->cfm_tag = xstrdup(val); 1392 return 0; 1393} 1394 1395 1396/* 1397 * Process one collected map. 1398 */ 1399static int 1400process_one_regular_map(const cf_map_t *cfm) 1401{ 1402 if (!cfm->cfm_name) { 1403 fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir); 1404 return 1; 1405 } 1406 /* 1407 * If map has no tag defined, process the map. 1408 * If no conf_tag was set in amd -T, process all untagged entries. 1409 * If a tag is defined, then process it only if it matches the map tag. 1410 */ 1411 if (!cfm->cfm_tag || 1412 (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) { 1413#ifdef DEBUG_CONF 1414 fprintf(stderr, "processing map %s (flags=0x%x)...\n", 1415 cfm->cfm_dir, cfm->cfm_flags); 1416#endif /* DEBUG_CONF */ 1417 root_newmap(cfm->cfm_dir, 1418 cfm->cfm_opts ? cfm->cfm_opts : "", 1419 cfm->cfm_name, 1420 cfm); 1421 } else { 1422 fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir); 1423 } 1424 1425 return 0; 1426} 1427 1428 1429/* 1430 * Process all regular maps in conf file (if any) 1431 */ 1432int 1433process_all_regular_maps(void) 1434{ 1435 cf_map_t *tmp_map = head_map; 1436 1437 /* 1438 * If the amd.conf file only has a [global] section (pretty useless 1439 * IMHO), there's nothing to process 1440 */ 1441 if (!tmp_map) 1442 return 0; 1443 1444 while (tmp_map) { 1445 if (process_one_regular_map(tmp_map) != 0) 1446 return 1; 1447 tmp_map = tmp_map->cfm_next; 1448 } 1449 return 0; 1450} 1451 1452 1453/* 1454 * Find a cf_map_t for a given map name. 1455 * Return NULL if not found. 1456 */ 1457cf_map_t * 1458find_cf_map(const char *name) 1459{ 1460 1461 cf_map_t *tmp_map = head_map; 1462 1463 if (!tmp_map || !name) 1464 return NULL; 1465 1466 while (tmp_map) { 1467 if (STREQ(tmp_map->cfm_dir, name)) { 1468 return tmp_map; 1469 } 1470 tmp_map = tmp_map->cfm_next; 1471 } 1472 return NULL; 1473} 1474