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