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