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