xref: /csrg-svn/usr.sbin/amd/include/am.h (revision 47527)
1 /*
2  * $Id: am.h,v 5.2.1.5 91/03/17 17:38:03 jsp Alpha $
3  *
4  * Copyright (c) 1990 Jan-Simon Pendry
5  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6  * Copyright (c) 1990 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Jan-Simon Pendry at Imperial College, London.
11  *
12  * %sccs.include.redist.c%
13  *
14  *	@(#)am.h	5.2 (Berkeley) 03/17/91
15  */
16 
17 #include "config.h"
18 
19 /*
20  * Global declarations
21  */
22 #include <sys/param.h>
23 #include <sys/socket.h>
24 #include <rpc/rpc.h>
25 #include "nfs_prot.h"
26 #ifdef MNTENT_HDR
27 #include MNTENT_HDR
28 #endif /* MNTENT_HDR */
29 #include <assert.h>
30 
31 #ifdef DEBUG_MEM
32 #include <malloc.h>
33 #endif /* DEBUG_MEM */
34 
35 #ifndef MAXHOSTNAMELEN
36 #define MAXHOSTNAMELEN 64
37 #endif /* MAXHOSTNAMELEN */
38 
39 #ifndef MNTTYPE_AUTO
40 #define MNTTYPE_AUTO "auto"
41 #endif /* MNTTYPE_AUTO */
42 
43 #ifndef FALSE
44 #define FALSE 0
45 #define TRUE 1
46 #endif /* FALSE */
47 
48 #ifndef ROOT_MAP
49 #define	ROOT_MAP "\"root\""
50 #endif /* ROOT_MAP */
51 
52 /*
53  * Flags from command line
54  */
55 extern int print_pid;		/* Print pid to stdout */
56 extern int normalize_hosts;	/* Normalize host names before use */
57 extern int restart_existing_mounts;
58 #ifdef HAS_NIS_MAPS
59 extern char *domain;		/* NIS domain to use */
60 #endif /* HAS_NIS_MAPS */
61 extern int am_timeo;		/* Cache period */
62 extern int afs_timeo;		/* AFS timeout */
63 extern int afs_retrans;		/* AFS retrans */
64 extern int am_timeo_w;		/* Unmount timeout */
65 extern char *mtab;		/* Mount table */
66 
67 typedef enum {
68 	Start,
69 	Run,
70 	Finishing,
71 	Quit,
72 	Done
73 } serv_state;
74 
75 extern serv_state amd_state;	/* Should we go now */
76 extern int immediate_abort;	/* Should close-down unmounts be retried */
77 extern time_t do_mapc_reload;	/* Flush & reload mount map cache */
78 
79 /*
80  * Useful constants
81  */
82 extern char pid_fsname[];	/* kiska.southseas.nz:(pid%d) */
83 extern char hostd[];		/* "kiska.southseas.nz" */
84 extern char *hostdomain;	/* "southseas.nz" */
85 extern char *op_sys;		/* "sos4" */
86 extern char *arch;		/* "sun4" */
87 extern char *karch;		/* "sun4c" */
88 extern char *cluster;		/* "r+d-kluster" */
89 extern char *endian;		/* "big" */
90 extern char *auto_dir;		/* "/a" */
91 extern char copyright[];	/* Copyright info */
92 extern char version[];		/* Version info */
93 
94 typedef struct am_ops am_ops;
95 typedef struct am_node am_node;
96 typedef struct am_opts am_opts;
97 typedef struct mntfs mntfs;
98 typedef struct fserver fserver;
99 typedef struct fsrvinfo fsrvinfo;
100 
101 /*
102  * Debug defns.
103  */
104 #ifdef DEBUG
105 #define	DEBUG_MTAB	"./mtab"
106 
107 extern int debug_flags;		/* Debug options */
108 
109 #define	D_DAEMON	0x0001	/* Enter daemon mode */
110 #define	D_TRACE		0x0002	/* Do protocol trace */
111 #define	D_FULL		0x0004	/* Do full trace */
112 #define	D_MTAB		0x0008	/* Use local mtab */
113 #define	D_AMQ		0x0010	/* Register amq program */
114 #define	D_STR		0x0020	/* Debug string munging */
115 #define	D_MEM		0x0040	/* Trace memory allocations */
116 
117 /*
118  * Normally, don't enter daemon mode, and don't register amq
119  */
120 #define	D_TEST	(~(D_DAEMON|D_MEM|D_STR))
121 #endif /* DEBUG */
122 
123 /*
124  * Global variables.
125  */
126 extern unsigned short nfs_port;	/* Our NFS service port */
127 extern struct in_addr myipaddr;	/* (An) IP address of this host */
128 
129 extern int foreground;		/* Foreground process */
130 extern time_t next_softclock;	/* Time to call softclock() */
131 extern int task_notify_todo;	/* Task notifier needs running */
132 #ifdef HAS_TFS
133 extern int nfs_server_code_available;
134 #endif /* HAS_TFS */
135 extern int last_used_map;	/* Last map being used for mounts */
136 extern AUTH *nfs_auth;		/* Dummy uthorisation for remote servers */
137 extern am_node **exported_ap;	/* List of nodes */
138 extern int first_free_map;	/* First free node */
139 extern am_node *root_node;	/* Node for "root" */
140 extern char *wire;		/* Name of primary connected network */
141 #define	NEXP_AP	(254)
142 #define NEXP_AP_MARGIN (128)
143 
144 typedef int (*task_fun)P((voidp));
145 typedef void (*cb_fun)P((int, int, voidp));
146 typedef void (*fwd_fun)P((voidp, int, struct sockaddr_in *,
147 				struct sockaddr_in *, voidp, int));
148 
149 /*
150  * String comparison macros
151  */
152 #define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
153 #define FSTREQ(s1, s2) ((*(s1) == *(s2)) && STREQ((s1),(s2)))
154 
155 /*
156  * Linked list
157  */
158 typedef struct qelem qelem;
159 struct qelem {
160 	qelem *q_forw;
161 	qelem *q_back;
162 };
163 #define	FIRST(ty, q)	((ty *) ((q)->q_forw))
164 #define	LAST(ty, q)	((ty *) ((q)->q_back))
165 #define	NEXT(ty, q)	((ty *) (((qelem *) q)->q_forw))
166 #define	PREV(ty, q)	((ty *) (((qelem *) q)->q_back))
167 #define	HEAD(ty, q)	((ty *) q)
168 #define	ITER(v, ty, q) \
169 	for ((v) = FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
170 
171 /*
172  * List of mount table entries
173  */
174 typedef struct mntlist mntlist;
175 struct mntlist {
176 	struct mntlist *mnext;
177 	struct mntent *mnt;
178 };
179 
180 /*
181  * Mount map
182  */
183 typedef struct mnt_map mnt_map;
184 
185 /*
186  * Global routines
187  */
188 extern int atoi P((Const char *)); /* C */
189 extern void am_mounted P((am_node*));
190 extern void am_unmounted P((am_node*));
191 extern int background(P_void);
192 extern int bind_resv_port P((int, unsigned short*));
193 extern int compute_mount_flags P((struct mntent *));
194 extern int softclock(P_void);
195 #ifdef DEBUG
196 extern int debug_option P((char*));
197 #endif /* DEBUG */
198 extern void deslashify P((char*));
199 /*extern void domain_strip P((char*, char*));*/
200 extern mntfs* dup_mntfs P((mntfs*));
201 extern fserver* dup_srvr P((fserver*));
202 extern int eval_fs_opts P((am_opts*, char*, char*, char*, char*, char*));
203 extern char* expand_key P((char*));
204 extern am_node* exported_ap_alloc(P_void);
205 extern am_node* find_ap P((char*));
206 extern am_node* find_mf P((mntfs*));
207 extern mntfs* find_mntfs P((am_ops*, am_opts*, char*, char*, char*, char*));
208 extern void flush_mntfs(P_void);
209 extern void flush_nfs_fhandle_cache P((fserver*));
210 extern void forcibly_timeout_mp P((am_node*));
211 extern FREE_RETURN_TYPE free P((voidp)); /* C */
212 extern void free_mntfs P((mntfs*));
213 extern void free_opts P((am_opts*));
214 extern void free_map P((am_node*));
215 extern void free_mntlist P((mntlist*));
216 extern void free_srvr P((fserver*));
217 extern int fwd_init(P_void);
218 extern int fwd_packet P((int, voidp, int, struct sockaddr_in *,
219 		struct sockaddr_in *, voidp, fwd_fun));
220 extern void fwd_reply(P_void);
221 extern void get_args P((int, char*[]));
222 extern char *getwire P((void));
223 #ifdef NEED_MNTOPT_PARSER
224 extern char *hasmntopt P((struct mntent*, char*));
225 #endif /* NEED_MNTOPT_PARSER */
226 extern int hasmntval P((struct mntent*, char*));
227 extern void host_normalize P((char **));
228 extern char *inet_dquad P((char*, unsigned long));
229 extern void init_map P((am_node*, char*));
230 extern void insert_am P((am_node*, am_node*));
231 extern void ins_que P((qelem*, qelem*));
232 extern void make_root_node(P_void);
233 extern int make_rpc_packet P((char*, int, u_long, struct rpc_msg*, voidp, xdrproc_t, AUTH*));
234 extern void mapc_add_kv P((mnt_map*, char*, char*));
235 extern mnt_map* mapc_find P((char*, char*));
236 extern void mapc_free P((mnt_map*));
237 extern int mapc_keyiter P((mnt_map*, void (*)(char*,voidp), voidp));
238 extern int mapc_search P((mnt_map*, char*, char**));
239 extern void mapc_reload(P_void);
240 extern void mapc_showtypes P((FILE*));
241 extern int mkdirs P((char*, int));
242 extern void mk_fattr P((am_node*, enum ftype));
243 extern void mnt_free P((struct mntent*));
244 extern int mount_auto_node P((char*, voidp));
245 extern int mount_automounter P((int));
246 extern int mount_exported(P_void);
247 extern int mount_fs P((struct mntent*, int, caddr_t, int, MTYPE_TYPE));
248 extern int mount_node P((am_node*));
249 extern mntfs* new_mntfs(P_void);
250 extern void new_ttl P((am_node*));
251 extern am_node* next_map P((int*));
252 extern int nfs_srvr_port P((fserver*, u_short*, voidp));
253 extern void normalize_slash P((char*));
254 extern void ops_showfstypes P((FILE*));
255 extern int pickup_rpc_reply P((voidp, int, voidp, xdrproc_t));
256 extern mntlist* read_mtab P((char*));
257 extern mntfs* realloc_mntfs  P((mntfs*, am_ops*, am_opts*, char*, char*, char*, char*));
258 extern void rem_que P((qelem*));
259 extern void reschedule_timeout_mp(P_void);
260 extern void restart(P_void);
261 #ifdef UPDATE_MTAB
262 extern void rewrite_mtab P((mntlist *));
263 #endif /* UPDATE_MTAB */
264 extern void rmdirs P((char*));
265 extern am_node* root_ap P((char*, int));
266 extern int root_keyiter P((void (*)(char*,voidp), voidp));
267 extern void root_newmap P((char*, char*, char*));
268 extern void rpc_msg_init P((struct rpc_msg*, u_long, u_long, u_long));
269 extern void run_task P((task_fun, voidp, cb_fun, voidp));
270 extern void sched_task P((cb_fun, voidp, voidp));
271 extern void show_rcs_info P((Const char*, char*));
272 extern void sigchld P((int));
273 extern void srvrlog P((fserver*, char*));
274 extern char* str3cat P((char*, char*, char*, char*));
275 extern char* strcat P((char*, Const char*)); /* C */
276 extern int strcmp P((Const char*, Const char*)); /* C */
277 extern char* strdup P((Const char*));
278 extern int strlen P((Const char*)); /* C */
279 extern char* strnsave P((Const char*, int));
280 extern char* strrchr P((Const char*, int)); /* C */
281 extern char* strealloc P((char*, char *));
282 extern char** strsplit P((char*, int, int));
283 extern int switch_option P((char*));
284 extern int switch_to_logfile P((char*));
285 extern void do_task_notify(P_void);
286 extern int timeout P((unsigned int, void (*fn)(), voidp));
287 extern void timeout_mp(P_void);
288 extern void umount_exported(P_void);
289 extern int umount_fs P((char*));
290 /*extern int unmount_node P((am_node*));
291 extern int unmount_node_wrap P((voidp));*/
292 extern void unregister_amq(P_void);
293 extern void untimeout P((int));
294 extern int valid_key P((char*));
295 extern void wakeup P((voidp));
296 extern void wakeup_task P((int,int,voidp));
297 extern void wakeup_srvr P((fserver*));
298 extern void write_mntent P((struct mntent*));
299 #ifdef UPDATE_MTAB
300 extern void unlock_mntlist P((void));
301 #else
302 #define	unlock_mntlist()
303 #endif /* UPDATE_MTAB */
304 
305 
306 #define	ALLOC(ty)	((struct ty *) xmalloc(sizeof(struct ty)))
307 
308 /*
309  * Options
310  */
311 struct am_opts {
312 	char	*fs_glob;		/* Smashed copy of global options */
313 	char	*fs_local;		/* Expanded copy of local options */
314 	char	*fs_mtab;		/* Mount table entry */
315 	/* Other options ... */
316 	char	*opt_dev;
317 	char	*opt_delay;
318 	char	*opt_dir;
319 	char	*opt_fs;
320 	char	*opt_group;
321 	char	*opt_mount;
322 	char	*opt_opts;
323 	char	*opt_pref;
324 	char	*opt_cache;
325 	char	*opt_rfs;
326 	char	*opt_rhost;
327 	char	*opt_sublink;
328 	char	*opt_type;
329 	char	*opt_unmount;
330 	char	*opt_user;
331 };
332 
333 /*
334  * File Handle
335  *
336  * This is interpreted by indexing the exported array
337  * by fhh_id.
338  *
339  * The whole structure is mapped onto a standard fhandle_t
340  * when transmitted.
341  */
342 struct am_fh {
343 	int	fhh_pid;		/* process id */
344 	int	fhh_id;			/* map id */
345 	int	fhh_gen;		/* generation number */
346 };
347 
348 extern am_node *fh_to_mp P((nfs_fh*));
349 extern am_node *fh_to_mp3 P((nfs_fh*,int*,int));
350 extern void mp_to_fh P((am_node*, nfs_fh*));
351 #define	fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
352 extern int auto_fmount P((am_node *mp));
353 extern int auto_fumount P((am_node *mp));
354 
355 #define	MAX_READDIR_ENTRIES	16
356 
357 typedef char*	(*vfs_match)P((am_opts*));
358 typedef int	(*vfs_init)P((mntfs*));
359 typedef int	(*vmount_fs)P((am_node*));
360 typedef int	(*vfmount_fs)P((mntfs*));
361 typedef int	(*vumount_fs)P((am_node*));
362 typedef int	(*vfumount_fs)P((mntfs*));
363 typedef am_node*(*vlookuppn)P((am_node*, char*, int*, int));
364 typedef int	(*vreaddir)P((am_node*, nfscookie, dirlist*, entry*, int));
365 typedef am_node*(*vreadlink)P((am_node*, int*));
366 typedef void	(*vmounted)P((mntfs*));
367 typedef void	(*vumounted)P((am_node*));
368 typedef fserver*(*vffserver)P((mntfs*));
369 
370 struct am_ops {
371 	char		*fs_type;
372 	vfs_match	fs_match;
373 	vfs_init	fs_init;
374 	vmount_fs	mount_fs;
375 	vfmount_fs	fmount_fs;
376 	vumount_fs	umount_fs;
377 	vfumount_fs	fumount_fs;
378 	vlookuppn	lookuppn;
379 	vreaddir	readdir;
380 	vreadlink	readlink;
381 	vmounted	mounted;
382 	vumounted	umounted;
383 	vffserver	ffserver;
384 	int		fs_flags;
385 };
386 extern am_node *efs_lookuppn P((am_node*, char*, int*, int));
387 extern int efs_readdir P((am_node*, nfscookie, dirlist*, entry*, int));
388 
389 #define	VLOOK_CREATE	0x1
390 #define	VLOOK_DELETE	0x2
391 
392 #define FS_DIRECTORY	0x0001		/* This looks like a dir, not a link */
393 #define	FS_MBACKGROUND	0x0002		/* Should background this mount */
394 #define	FS_NOTIMEOUT	0x0004		/* Don't bother with timeouts */
395 #define FS_MKMNT	0x0008		/* Need to make the mount point */
396 #define FS_UBACKGROUND	0x0010		/* Unmount in background */
397 #define	FS_BACKGROUND	(FS_MBACKGROUND|FS_UBACKGROUND)
398 #define	FS_DISCARD	0x0020		/* Discard immediately on last reference */
399 #define	FS_AMQINFO	0x0040		/* Amq is interested in this fs type */
400 
401 #ifdef SUNOS4_COMPAT
402 extern am_ops *sunos4_match P((am_opts*, char*, char*, char*, char*, char*));
403 #endif /* SUNOS4_COMPAT */
404 extern am_ops *ops_match P((am_opts*, char*, char*, char*, char*, char*));
405 #include "fstype.h"
406 
407 /*
408  * Per-mountpoint statistics
409  */
410 struct am_stats {
411 	time_t	s_mtime;	/* Mount time */
412 	u_short	s_uid;		/* Uid of mounter */
413 	int	s_getattr;	/* Count of getattrs */
414 	int	s_lookup;	/* Count of lookups */
415 	int	s_readdir;	/* Count of readdirs */
416 	int	s_readlink;	/* Count of readlinks */
417 	int	s_statfs;	/* Count of statfs */
418 };
419 typedef struct am_stats am_stats;
420 
421 /*
422  * System statistics
423  */
424 struct amd_stats {
425 	int	d_drops;	/* Dropped requests */
426 	int	d_stale;	/* Stale NFS handles */
427 	int	d_mok;		/* Succesful mounts */
428 	int	d_merr;		/* Failed mounts */
429 	int	d_uerr;		/* Failed unmounts */
430 };
431 extern struct amd_stats amd_stats;
432 
433 /*
434  * List of fileservers
435  */
436 struct fserver {
437 	qelem		fs_q;		/* List of fileservers */
438 	int		fs_refc;	/* Number of references to this node */
439 	char		*fs_host;	/* Normalized hostname of server */
440 	struct sockaddr_in *fs_ip;	/* Network address of server */
441 	int		fs_cid;		/* Callout id */
442 	int		fs_pinger;	/* Ping (keepalive) interval */
443 	int		fs_flags;	/* Flags */
444 	char		*fs_type;	/* File server type */
445 	voidp		fs_private;	/* Private data */
446 	void		(*fs_prfree)();	/* Free private data */
447 };
448 #define	FSF_VALID	0x0001		/* Valid information available */
449 #define	FSF_DOWN	0x0002		/* This fileserver is thought to be down */
450 #define	FSF_ERROR	0x0004		/* Permanent error has occured */
451 #define	FSF_WANT	0x0008		/* Want a wakeup call */
452 #define	FSF_PINGING	0x0010		/* Already doing pings */
453 #define	FSRV_ISDOWN(fs)	(((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
454 #define	FSRV_ISUP(fs)	(((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
455 
456 /*
457  * List of mounted filesystems
458  */
459 struct mntfs {
460 	qelem		mf_q;		/* List of mounted filesystems */
461 	am_ops		*mf_ops;	/* Operations on this mountpoint */
462 	am_opts		*mf_fo;		/* File opts */
463 	char		*mf_mount;	/* "/a/kiska/home/kiska" */
464 	char		*mf_info;	/* Mount info */
465 	char		*mf_auto;	/* Automount opts */
466 	char		*mf_mopts;	/* FS mount opts */
467 	fserver		*mf_server;	/* File server */
468 	int		mf_flags;	/* Flags */
469 	int		mf_error;	/* Error code from background mount */
470 	int		mf_refc;	/* Number of references to this node */
471 	int		mf_cid;		/* Callout id */
472 	void		(*mf_prfree)();	/* Free private space */
473 	voidp		mf_private;	/* Private - per-fs data */
474 };
475 
476 #define	MFF_MOUNTED	0x0001		/* Node is mounted */
477 #define	MFF_MOUNTING	0x0002		/* Mount is in progress */
478 #define	MFF_UNMOUNTING	0x0004		/* Unmount is in progress */
479 #define	MFF_RESTART	0x0008		/* Restarted node */
480 #define MFF_MKMNT	0x0010		/* Delete this node's am_mount */
481 #define	MFF_ERROR	0x0020		/* This node failed to mount */
482 #define	MFF_LOGDOWN	0x0040		/* Logged that this mount is down */
483 #define	MFF_RSTKEEP	0x0080		/* Don't timeout this filesystem - restarted */
484 #define	MFF_WANTTIMO	0x0100		/* Need a timeout call when not busy */
485 
486 /*
487  * Map of auto-mount points.
488  */
489 struct am_node {
490 	int		am_mapno;	/* Map number */
491 	mntfs		*am_mnt;	/* Mounted filesystem */
492 	char		*am_name;	/* "kiska"
493 					   Name of this node */
494 	char		*am_path;	/* "/home/kiska"
495 					   Path of this node's mount point */
496 	char		*am_link;	/* "/a/kiska/home/kiska/this/that"
497 					   Link to sub-directory */
498 	am_node		*am_parent,	/* Parent of this node */
499 			*am_ysib,	/* Younger sibling of this node */
500 			*am_osib,	/* Older sibling of this node */
501 			*am_child;	/* First child of this node */
502 	struct attrstat	am_attr;	/* File attributes */
503 #define am_fattr	am_attr.attrstat_u.attributes
504 	int		am_flags;	/* Boolean flags */
505 	int		am_error;	/* Specific mount error */
506 	time_t		am_ttl;		/* Time to live */
507 	int		am_timeo_w;	/* Wait interval */
508 	int		am_timeo;	/* Timeout interval */
509 	unsigned int	am_gen;		/* Generation number */
510 	char		*am_pref;	/* Mount info prefix */
511 	am_stats	am_stats;	/* Statistics gathering */
512 };
513 
514 #define	AMF_NOTIMEOUT	0x0001		/* This node never times out */
515 #define	AMF_ROOT	0x0002		/* This is a root node */
516 
517 #define	ONE_HOUR	(60 * 60)	/* One hour in seconds */
518 
519 /*
520  * The following values can be tuned...
521  */
522 #define	ALLOWED_MOUNT_TIME	40		/* 40s for a mount */
523 #define	AM_TTL			(5 * 60)	/* Default cache period */
524 #define	AM_TTL_W		(2 * 60)	/* Default unmount interval */
525 #define	AM_PINGER		30		/* NFS ping interval for live systems */
526 #define	AFS_TIMEO		8		/* Default afs timeout - .8s */
527 #define	AFS_RETRANS		((ALLOWED_MOUNT_TIME*10+5*afs_timeo)/afs_timeo * 2)
528 						/* Default afs retrans - 1/10th seconds */
529 
530 #define	RPC_XID_PORTMAP		0
531 #define	RPC_XID_MOUNTD		1
532 #define	RPC_XID_NFSPING		2
533 #define	RPC_XID_MASK		(0x0f)		/* 16 id's for now */
534 #define	MK_RPC_XID(type_id, uniq)	((type_id) | ((uniq) << 4))
535