1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Portions Copyright 2007-2011 Apple Inc.
29 */
30
31#ifndef	_AUTOMOUNT_H
32#define	_AUTOMOUNT_H
33
34#pragma ident	"@(#)automount.h	1.69	05/09/30 SMI"
35
36#include <assert.h>
37#include <pthread.h>
38#include <sys/types.h>
39#include <sys/mount.h>		/* for fsid_t */
40#include <oncrpc/rpc.h>
41#include <netinet/in.h>		/* needed for sockaddr_in declaration */
42
43#include <mach/mach.h>
44
45#ifdef MALLOC_DEBUG
46#include <debug_alloc.h>
47#endif
48
49#include "autofs.h"
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55/*
56 * OS X autofs configuration file location
57 */
58#define	AUTOFSADMIN	"/etc/autofs.conf"
59
60#define	MXHOSTNAMELEN	64
61#define	MAXNETNAMELEN   255
62/* We can't supply names that don't fit in a "struct dirent" */
63#define	MAXFILENAMELEN	(sizeof (((struct dirent *)0)->d_name) - 1)
64#define	LINESZ		4096
65#define	MAXOPTSLEN	AUTOFS_MAXOPTSLEN
66
67#define	AUTOFS_MOUNT_TIMEOUT	600	/* default min time mount will */
68					/* remain mounted (in seconds) */
69#define	AUTOFS_RPC_TIMEOUT	60	/* secs autofs will wait for */
70					/* automountd's reply before */
71					/* retransmitting */
72/* stack ops */
73#define	ERASE		0
74#define	PUSH		1
75#define	POP		2
76#define	INIT		3
77#define	STACKSIZ	30
78
79#define	DIST_SELF	1
80#define	DIST_MYSUB	2
81#define	DIST_MYNET	3
82#define	DIST_OTHER	4
83
84#define	MAXIFS		32
85
86/*
87 * Retry operation related definitions.
88 */
89#define	RET_OK		0
90#define	RET_RETRY	32
91#define	RET_ERR		33
92#define	INITDELAY	5
93#define	DELAY_BACKOFF	2
94#define	MAXDELAY	120
95#define	DO_DELAY(delay) { \
96	(void) sleep(delay); \
97	delay *= DELAY_BACKOFF; \
98	if (delay > MAXDELAY) \
99		delay = MAXDELAY; \
100}
101
102struct mapline {
103	char linebuf[LINESZ];
104	char lineqbuf[LINESZ];
105};
106
107/*
108 * Typedefs present in Solaris but not in OS X.
109 */
110typedef unsigned char uchar_t;
111typedef unsigned short ushort_t;
112typedef unsigned int uint_t;
113typedef uint32_t rpcprog_t;
114typedef uint32_t rpcvers_t;
115
116/*
117 * XXX - kill me if possible.
118 */
119struct mnttab {
120	char	*mnt_special;
121	char	*mnt_mountp;
122	char	*mnt_fstype;
123	char	*mnt_mntopts;
124	char	*mnt_time;
125};
126
127/*
128 * Structure describing a host/filesystem/dir tuple in a NIS map entry
129 */
130struct mapfs {
131	struct mapfs *mfs_next;	/* next in entry */
132	int	mfs_ignore;	/* ignore this entry */
133	char	*mfs_host;	/* host name */
134	char	*mfs_dir;	/* dir to mount */
135	int	mfs_penalty;	/* mount penalty for this host */
136	int	mfs_distance;	/* distance hint */
137	struct nfs_args *mfs_args;	/* nfs_args */
138	rpcvers_t	mfs_version;	/* NFS version */
139
140#define	MFS_ALLOC_DIR		0x1	/* mfs_dir now points to different */
141					/* buffer */
142
143#define	MFS_URL			0x2	/* is NFS url listed in this tuple. */
144#define	MFS_FH_VIA_WEBNFS	0x4	/* got file handle during ping phase */
145
146	uint_t	mfs_flags;
147	uint_t	mfs_port;	/* port# in NFS url */
148};
149
150/*
151 * NIS entry - lookup of name in DIR gets us this
152 */
153struct mapent {
154	char	*map_fstype;	/* file system type e.g. "nfs" */
155	char	*map_mounter;	/* base fs e.g. "cachefs" */
156	char	*map_root;	/* path to mount root */
157	char	*map_mntpnt;	/* path from mount root */
158	char	*map_mntopts;	/* mount options */
159	char    *map_fsw;	/* mount fs information */
160	char    *map_fswq;	/* quoted mountfs information */
161	int	map_mntlevel;	/* mapentry hierarchy level */
162	bool_t	map_modified;	/* flags modified mapentries */
163	bool_t	map_faked;	/* flags faked mapentries */
164	int	map_err;	/* flags any bad entries in the map */
165	struct mapfs *map_fs;	/* list of replicas for nfs */
166	struct mapent *map_next;
167};
168
169
170/*
171 * Descriptor for each directory served by the automounter
172 */
173struct autodir {
174	char	*dir_name;		/* mount point */
175	char	*dir_map;		/* name of map for dir */
176	char	*dir_opts;		/* default mount options */
177	int	dir_direct;		/* direct mountpoint ? */
178	char	*dir_realpath;		/* realpath() of mount point - not always set */
179	struct autodir *dir_next;	/* next entry */
180	struct autodir *dir_prev;	/* prev entry */
181};
182
183/*
184 * This structure is used to build an array of
185 * hostnames with associated penalties to be
186 * passed to the nfs_cast procedure
187 */
188struct host_names {
189	char *host;
190	int  penalty;
191};
192
193/*
194 * structure used to build list of contents for a map on
195 * a readdir request
196 */
197struct dir_entry {
198	char		*name;		/* name of entry */
199	ino_t		nodeid;
200	off_t		offset;
201	char		*line;		/* map line for entry, or NULL */
202	char		*lineq;		/* map quote line for entry, or NULLs */
203	struct dir_entry *next;
204	struct dir_entry *left;		/* left element in binary tree */
205	struct dir_entry *right;	/* right element in binary tree */
206};
207
208/*
209 * offset index table
210 */
211struct off_tbl {
212	off_t			offset;
213	struct dir_entry	*first;
214	struct off_tbl		*next;
215};
216
217#ifndef NO_RDDIR_CACHE
218/*
219 * directory cache for 'map'
220 */
221struct rddir_cache {
222	char			*map;
223	struct off_tbl		*offtp;
224	uint_t			bucket_size;
225	time_t			ttl;
226	struct dir_entry	*entp;
227	pthread_mutex_t		lock;		/* protects 'in_use' field */
228	int			in_use;		/* # threads referencing it */
229	pthread_rwlock_t	rwlock;		/* protects 'full' and 'next' */
230	int			full;		/* full == 1 when cache full */
231	struct rddir_cache	*next;
232};
233
234#define	RDDIR_CACHE_TIME	300		/* in seconds */
235
236#endif /* NO_RDDIR_CACHE */
237
238/*
239 * structure used to maintain address list for localhost
240 */
241
242struct myaddrs {
243	struct sockaddr_in sin;
244	struct myaddrs *myaddrs_next;
245};
246
247extern time_t timenow;	/* set at start of processing of each RPC call */
248extern char self[];
249extern int verbose;
250extern int trace;
251extern struct autodir *dir_head;
252extern struct autodir *dir_tail;
253struct autofs_args;
254extern struct myaddrs *myaddrs_head;
255
256extern pthread_rwlock_t	cache_lock;
257extern pthread_rwlock_t rddir_cache_lock;
258
259extern pthread_mutex_t cleanup_lock;
260extern pthread_cond_t cleanup_start_cv;
261extern pthread_cond_t cleanup_done_cv;
262
263/*
264 * "Safe" string operations; used with string buffers already
265 * allocated to be large enough, so we just abort if this fails.
266 */
267#define CHECK_STRCPY(a, b, size) \
268	strlcpy(a, b, (size)) < (size) ? 0 : -1
269
270#define CHECK_STRCAT(a, b, size) \
271	strlcat((a), (b), (size)) < (size) ? 0 : -1
272
273/*
274 * mnttab handling routines
275 */
276extern void free_mapent(struct mapent *);
277
278#define MNTTYPE_NFS	"nfs"
279#define MNTTYPE_LOFS	"lofs"
280
281/*
282 * utilities
283 */
284extern struct mapent *parse_entry(const char *, const char *, const char *,
285				const char *, uint_t, int *, bool_t, bool_t,
286				int *);
287typedef enum {
288	MEXPAND_OK,			/* expansion worked */
289	MEXPAND_LINE_TOO_LONG,		/* line too long */
290	MEXPAND_VARNAME_TOO_LONG	/* variable name too long */
291} macro_expand_status;
292extern macro_expand_status macro_expand(const char *, char *, char *, int);
293extern void unquote(char *, char *);
294extern void trim(char *);
295extern char *get_line(FILE *, char *, char *, int);
296extern int getword(char *, char *, char **, char **, char, int);
297extern int get_retry(const char *);
298extern int str_opt(struct mnttab *, char *, char **);
299extern void dirinit(char *, char *, char *, int, char **, char ***);
300extern void pr_msg(const char *, ...) __printflike(1, 2);
301extern void trace_prt(int, char *, ...) __printflike(2, 3);
302extern void free_action_list_fields(action_list *);
303
304extern int nopt(struct mnttab *, char *, int *);
305extern int set_versrange(rpcvers_t, rpcvers_t *, rpcvers_t *);
306extern enum clnt_stat pingnfs(const char *, rpcvers_t *, rpcvers_t,
307	ushort_t, const char *, const char *);
308
309extern int self_check(char *);
310extern int host_is_us(const char *, size_t);
311extern void flush_host_name_cache(void);
312extern int we_are_a_server(void);
313extern int do_mount1(const autofs_pathname, const char *,
314	const autofs_pathname, const autofs_opts, const autofs_pathname,
315	boolean_t, boolean_t, fsid_t, uid_t, au_asid_t, fsid_t *,
316	uint32_t *, byte_buffer *, mach_msg_type_number_t *);
317extern int do_lookup1(const autofs_pathname, const char *,
318	const autofs_pathname, const autofs_opts, boolean_t, uid_t, int *);
319extern int do_unmount1(fsid_t, autofs_pathname, autofs_pathname,
320	autofs_component, autofs_opts);
321extern int do_readdir(autofs_pathname, off_t, uint32_t, off_t *,
322	boolean_t *, byte_buffer *, mach_msg_type_number_t *);
323extern int do_readsubdir(autofs_pathname, char *, autofs_pathname,
324	autofs_opts, uint32_t, off_t, uint32_t, off_t *, boolean_t *,
325	byte_buffer *, mach_msg_type_number_t *);
326extern int nfsunmount(fsid_t *, struct mnttab *);
327extern int loopbackmount(char *, char *, char *);
328extern int mount_nfs(struct mapent *, char *, char *, boolean_t,
329	fsid_t, au_asid_t, fsid_t *, uint32_t *);
330extern int mount_autofs(const char *, struct mapent *, const char *, fsid_t,
331	action_list **, const char *, const char *, const char *, fsid_t *,
332	uint32_t *);
333extern int mount_generic(char *, char *, char *, int, char *, boolean_t,
334	boolean_t, fsid_t, uid_t, au_asid_t, fsid_t *, uint32_t *);
335extern int get_triggered_mount_info(const char *, fsid_t, fsid_t *,
336	uint32_t *);
337extern enum clnt_stat nfs_cast(struct mapfs *, struct mapfs **, int);
338
339extern bool_t hasrestrictopt(const char *);
340
341extern void flush_caches(void);
342
343#ifndef NO_RDDIR_CACHE
344/*
345 * readdir handling routines
346 */
347extern char *auto_rddir_malloc(unsigned);
348extern char *auto_rddir_strdup(const char *);
349extern struct dir_entry *btree_lookup(struct dir_entry *, const char *);
350extern void btree_enter(struct dir_entry **, struct dir_entry *);
351extern int add_dir_entry(const char *, const char *, const char *,
352	struct dir_entry **, struct dir_entry **);
353extern void *cache_cleanup(void *);
354extern struct dir_entry *rddir_entry_lookup(const char *, const char *);
355#endif /* NO_RDDIR_CACHE */
356
357/*
358 * generic interface to specific name service functions
359 */
360extern void ns_setup(char **, char ***);
361extern int getmapent(const char *, const char *, struct mapline *, char **,
362			char ***, bool_t *, bool_t);
363extern int getmapkeys(char *, struct dir_entry **, int *, int *, char **,
364			char ***);
365extern int loadmaster_map(char *, char *, char **, char ***);
366extern int loaddirect_map(char *, char *, char *, char **, char ***);
367
368/*
369 * Name service return statuses.
370 */
371#define	__NSW_SUCCESS	0	/* found the required data */
372#define	__NSW_NOTFOUND	1	/* the naming service returned lookup failure */
373#define	__NSW_UNAVAIL	2	/* could not call the naming service */
374
375/*
376 * these name service specific functions should not be
377 * accessed directly, use the generic functions.
378 */
379extern void init_files(char **, char ***);
380extern int getmapent_files(const char *, const char *, struct mapline *,
381				char **, char ***, bool_t *, bool_t);
382extern int loadmaster_files(char *, char *, char **, char ***);
383extern int loaddirect_files(char *, char *, char *, char **, char ***);
384extern int getmapkeys_files(char *, struct dir_entry **, int *, int *,
385	char **, char ***);
386extern int stack_op(int, char *, char **, char ***);
387
388extern void init_od(char **, char ***);
389extern int getmapent_od(const char *, const char *, struct mapline *, char **,
390				char ***, bool_t *, bool_t);
391extern int loadmaster_od(char *, char *, char **, char ***);
392extern int loaddirect_od(char *, char *, char *, char **, char ***);
393extern int getmapkeys_od(char *, struct dir_entry **, int *, int *,
394	char **, char ***);
395/*
396 * Node for fstab entry.
397 */
398struct fstabnode {
399	char	*fst_dir;	/* directory part of fs_spec */
400	char	*fst_vfstype;	/* fs_vfstype */
401	char	*fst_mntops;	/* fs_mntops plus fs_type */
402	char	*fst_url;	/* URL from fs_mntops, if fs_vfstype is "url" */
403	struct fstabnode *fst_next;
404};
405
406/*
407 * Structure for a static map entry (non-"net") in fstab.
408 */
409struct staticmap {
410	char	*dir;			/* name of the directory on which to mount */
411	char	*vfstype;		/* fs_vfstype */
412	char	*mntops;		/* fs_mntops plus fs_type */
413	char	*host;			/* host from which to mount */
414	char	*localpath;		/* full path, on the server, for that item */
415	char	*spec;			/* item to mount */
416	struct staticmap *next;		/* next entry in hash table bucket */
417};
418
419/*
420 * Look up a particular host in the fstab map hash table and, if we find it,
421 * run the callback routine on each entry in its fstab entry list.
422 */
423extern int fstab_process_host(const char *host,
424    int (*callback)(struct fstabnode *, void *), void *callback_arg);
425
426/*
427 * Enumerate all the entries in the -fstab map.
428 * This is used by a readdir on the -fstab map; those are likely to
429 * be followed by stats on one or more of the entries in that map, so
430 * we populate the fstab map cache and return values from that.
431 */
432extern int getfstabkeys(struct dir_entry **list, int *error, int *cache_time);
433
434/*
435 * Check whether we have any entries in the -fstab map.
436 * This is used by automount to decide whether to mount that map
437 * or not.
438 */
439extern int havefstabkeys(void);
440
441/*
442 * Load the -static direct map.
443 */
444extern int loaddirect_static(char *local_map, char *opts, char **stack,
445    char ***stkptr);
446
447/*
448 * Find the -static map entry corresponding to a given mount point.
449 */
450extern struct staticmap *get_staticmap_entry(const char *dir);
451
452/*
453 * Indicate that we're done with a -static map entry returned by
454 * get_staticmap_entry().
455 */
456extern void release_staticmap_entry(struct staticmap *static_ent);
457
458/*
459 * Purge the fstab cache; if scheduled is true, do so only if it's
460 * stale, otherwise do it unconditionally.
461 */
462extern void clean_fstab_cache(int scheduled);
463
464/*
465 * end of name service specific functions
466 */
467
468/*
469 * not defined in any header file
470 */
471extern int getnetmaskbynet(const struct in_addr, struct in_addr *);
472
473/*
474 * Hidden rpc functions
475 */
476extern int __nis_reset_state();
477extern int __rpc_negotiate_uid(int);
478extern int __rpc_get_local_uid(SVCXPRT *, uid_t *);
479
480#ifdef __cplusplus
481}
482#endif
483
484#endif	/* _AUTOMOUNT_H */
485