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