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