1/*	$NetBSD$	*/
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