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