#include "config.h"
#include <sys/signal.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <sys/mount.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "nfs_prot.h"
#include <assert.h>
#define MNTMAXSTR 128
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
#ifndef ROOT_MAP
#define ROOT_MAP "\"root\""
#endif
extern int print_pid;
extern int normalize_hosts;
extern int restart_existing_mounts;
extern char *domain;
extern int am_timeo;
extern int afs_timeo;
extern int afs_retrans;
extern int am_timeo_w;
extern char *mtab;
typedef enum {
Start,
Run,
Finishing,
Quit,
Done
} serv_state;
extern serv_state amd_state;
extern volatile sig_atomic_t immediate_abort;
extern time_t do_mapc_reload;
extern char pid_fsname[];
extern char hostd[];
extern char *hostdomain;
extern char *op_sys;
extern char *arch;
extern char *karch;
extern char *cluster;
extern char *endian;
extern char *auto_dir;
extern char version[];
typedef struct am_ops am_ops;
typedef struct am_node am_node;
typedef struct am_opts am_opts;
typedef struct mntfs mntfs;
typedef struct fserver fserver;
typedef struct fsrvinfo fsrvinfo;
#ifdef DEBUG
#define DEBUG_MTAB "./mtab"
extern int debug_flags;
#define D_DAEMON 0x0001
#define D_TRACE 0x0002
#define D_FULL 0x0004
#define D_MTAB 0x0008
#define D_AMQ 0x0010
#define D_STR 0x0020
#define D_MEM 0x0040
#define D_TEST (~(D_DAEMON|D_MEM|D_STR))
#endif
extern unsigned short nfs_port;
extern struct in_addr myipaddr;
extern int foreground;
extern time_t next_softclock;
extern int task_notify_todo;
#ifdef HAS_TFS
extern int nfs_server_code_available;
#endif
extern int last_used_map;
extern AUTH *nfs_auth;
extern am_node **exported_ap;
extern int first_free_map;
extern am_node *root_node;
extern char *wire;
#define NEXP_AP (254)
#define NEXP_AP_MARGIN (128)
typedef int (*task_fun)(void *);
typedef void (*cb_fun)(int, int, void *);
typedef void (*fwd_fun)(void *, int, struct sockaddr_in *,
struct sockaddr_in *, void *, int);
#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
#define FSTREQ(s1, s2) ((*(s1) == *(s2)) && STREQ((s1),(s2)))
typedef struct qelem qelem;
struct qelem {
qelem *q_forw;
qelem *q_back;
};
#define FIRST(ty, q) ((ty *) ((q)->q_forw))
#define LAST(ty, q) ((ty *) ((q)->q_back))
#define NEXT(ty, q) ((ty *) (((qelem *) q)->q_forw))
#define PREV(ty, q) ((ty *) (((qelem *) q)->q_back))
#define HEAD(ty, q) ((ty *) q)
#define ITER(v, ty, q) \
for ((v) = FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
struct mntent {
char *mnt_fsname;
char *mnt_dir;
char *mnt_type;
char *mnt_opts;
int mnt_freq;
int mnt_passno;
};
typedef struct mntlist mntlist;
struct mntlist {
struct mntlist *mnext;
struct mntent *mnt;
};
typedef struct mnt_map mnt_map;
struct fhstatus;
extern void am_mounted(am_node *);
extern void am_unmounted(am_node *);
extern void amq_program_57(struct svc_req *, SVCXPRT *);
extern pid_t background(void);
extern int bind_resv_port(int, unsigned short *);
extern int compute_mount_flags(struct mntent *);
extern int softclock(void);
#ifdef DEBUG
extern int debug_option(char *);
#endif
extern void deslashify(char *);
extern void discard_mntlist(mntlist *mp);
extern mntfs *dup_mntfs(mntfs *);
extern fserver *dup_srvr(fserver*);
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
extern char *expand_key(char *);
extern am_node *exported_ap_alloc(void);
extern am_node *find_ap(char *);
extern am_node *find_mf(mntfs *);
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *,
char *, char *);
extern void flush_mntfs(void);
extern void flush_nfs_fhandle_cache(fserver *);
extern void flush_srvr_nfs_cache(void);
extern void forcibly_timeout_mp(am_node *);
extern void free_mntfs(void *);
extern void free_opts(am_opts *);
extern void free_map(am_node *);
extern void free_mntlist(mntlist *);
extern void free_srvr(fserver *);
extern int fwd_init(void);
extern int fwd_packet(int, void *, int, struct sockaddr_in *,
struct sockaddr_in *, void *, fwd_fun);
extern void fwd_reply(void);
extern void get_args(int, char *[]);
extern char *getwire(void);
extern char *hasmntopt(struct mntent *, char *);
extern int hasmntval(struct mntent *, char *);
extern void host_normalize(char **);
extern char *inet_dquad(char *, size_t, u_int32_t);
extern void init_map(am_node *, char *);
extern void insert_am(am_node *, am_node *);
extern void ins_que(qelem *, qelem *);
extern int islocalnet(in_addr_t);
extern int make_nfs_auth(void);
extern void make_root_node(void);
extern int make_rpc_packet(char *, int, u_long, struct rpc_msg *,
void *, xdrproc_t, AUTH *);
extern void map_flush_srvr(fserver *);
extern void mapc_add_kv(mnt_map *, char *, char *);
extern mnt_map *mapc_find(char *, char *);
extern void mapc_free(void *);
extern int mapc_keyiter(mnt_map*, void (*)(char *,void *), void *);
extern int mapc_search(mnt_map *, char *, char **);
extern void mapc_reload(void);
extern void mapc_showtypes(FILE *);
extern void mf_mounted(mntfs *mf);
extern int mkdirs(char *, int);
extern void mk_fattr(am_node *, int);
extern void mnt_free(struct mntent *);
extern int mount_auto_node(char *, void *);
extern int mount_automounter(pid_t);
extern int mount_exported(void);
extern int mount_fs(struct mntent *, int, caddr_t, int, const char *);
extern int mount_nfs_fh(struct fhstatus *, char *, char *, char *, mntfs *);
extern int mount_node(am_node *);
extern mntfs *new_mntfs(void);
extern void new_ttl(am_node *);
extern am_node *next_map(int *);
extern int nfs_srvr_port(fserver *, u_short *, void *);
extern void nfs_program_2(struct svc_req *, SVCXPRT *);
extern void normalize_slash(char *);
extern void ops_showfstypes(FILE *);
extern int pickup_rpc_reply(void *, int, void *, xdrproc_t);
extern mntlist *read_mtab(char *);
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *,
char *, char *, char *, char *);
extern void rem_que(qelem *);
extern void reschedule_timeout_mp(void);
extern void reschedule_timeouts(time_t, time_t);
extern void restart(void);
extern nfs_fh *root_fh(char *);
extern void rmdirs(char *);
extern am_node *root_ap(char *, int);
extern int root_keyiter(void (*)(char *,void *), void *);
extern void root_newmap(char *, char *, char *);
extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long);
extern void run_task(task_fun, void *, cb_fun, void *);
extern void sched_task(cb_fun, void *, void *);
extern void show_rcs_info(const char *, char *);
extern void sigchld(int);
extern void srvrlog(fserver *, char *);
extern char *str3cat(char *, char *, char *, char *);
extern char *strnsave(const char *, int);
extern char *strealloc(char *, char *);
extern char **strsplit(char *, int, int);
extern int switch_option(char *);
extern int switch_to_logfile(char *);
extern void do_task_notify(void);
extern int timeout(unsigned int, void (*fn)(void *), void *);
extern void umount_exported(void);
extern int umount_fs(char *);
extern void unregister_amq(void);
extern void untimeout(int);
extern int valid_key(char *);
extern void wakeup(void *);
extern void wakeup_task(int, int, void *);
extern void wakeup_srvr(fserver *);
extern void write_mntent(struct mntent *);
#define ALLOC(ty) ((struct ty *) xmalloc(sizeof(struct ty)))
struct am_opts {
char *fs_glob;
char *fs_local;
char *fs_mtab;
char *opt_dev;
char *opt_delay;
char *opt_dir;
char *opt_fs;
char *opt_group;
char *opt_mount;
char *opt_opts;
char *opt_remopts;
char *opt_pref;
char *opt_cache;
char *opt_rfs;
char *opt_rhost;
char *opt_sublink;
char *opt_type;
char *opt_unmount;
char *opt_user;
};
struct am_fh {
int fhh_pid;
int fhh_id;
int fhh_gen;
};
extern am_node *fh_to_mp(nfs_fh *);
extern am_node *fh_to_mp3(nfs_fh *, int *, int);
extern void mp_to_fh(am_node *, nfs_fh *);
#define fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
extern int auto_fmount(am_node *mp);
extern int auto_fumount(am_node *mp);
#define MAX_READDIR_ENTRIES 16
typedef char *(*vfs_match)(am_opts *);
typedef int (*vfs_init)(mntfs *);
typedef int (*vmount_fs)(am_node *);
typedef int (*vfmount_fs)(mntfs *);
typedef int (*vumount_fs)(am_node *);
typedef int (*vfumount_fs)(mntfs *);
typedef am_node *(*vlookuppn)(am_node *, char *, int *, int);
typedef int (*vreaddir)(am_node *, nfscookie, dirlist *, entry *, int);
typedef am_node *(*vreadlink)(am_node *, int *);
typedef void (*vmounted)(mntfs *);
typedef void (*vumounted)(am_node *);
typedef fserver *(*vffserver)(mntfs *);
struct am_ops {
char *fs_type;
vfs_match fs_match;
vfs_init fs_init;
vmount_fs mount_fs;
vfmount_fs fmount_fs;
vumount_fs umount_fs;
vfumount_fs fumount_fs;
vlookuppn lookuppn;
vreaddir readdir;
vreadlink readlink;
vmounted mounted;
vumounted umounted;
vffserver ffserver;
int fs_flags;
};
extern am_node *efs_lookuppn(am_node *, char *, int *, int);
extern int efs_readdir(am_node *, nfscookie, dirlist *, entry *, int);
#define VLOOK_CREATE 0x1
#define VLOOK_DELETE 0x2
#define FS_DIRECTORY 0x0001
#define FS_MBACKGROUND 0x0002
#define FS_NOTIMEOUT 0x0004
#define FS_MKMNT 0x0008
#define FS_UBACKGROUND 0x0010
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
#define FS_DISCARD 0x0020
#define FS_AMQINFO 0x0040
#ifdef SUNOS4_COMPAT
extern am_ops *sunos4_match(am_opts *, char *, char *, char *, char *, char *);
#endif
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
#include "fstype.h"
struct am_stats {
time_t s_mtime;
u_short s_uid;
int s_getattr;
int s_lookup;
int s_readdir;
int s_readlink;
int s_statfs;
};
typedef struct am_stats am_stats;
struct amd_stats {
int d_drops;
int d_stale;
int d_mok;
int d_merr;
int d_uerr;
};
extern struct amd_stats amd_stats;
struct fserver {
qelem fs_q;
int fs_refc;
char *fs_host;
struct sockaddr_in *fs_ip;
int fs_cid;
int fs_pinger;
int fs_flags;
char *fs_type;
void *fs_private;
void (*fs_prfree)(void *);
};
#define FSF_VALID 0x0001
#define FSF_DOWN 0x0002
#define FSF_ERROR 0x0004
#define FSF_WANT 0x0008
#define FSF_PINGING 0x0010
#define FSRV_ISDOWN(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
#define FSRV_ISUP(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
struct mntfs {
qelem mf_q;
am_ops *mf_ops;
am_opts *mf_fo;
char *mf_mount;
char *mf_info;
char *mf_auto;
char *mf_mopts;
char *mf_remopts;
fserver *mf_server;
int mf_flags;
int mf_error;
int mf_refc;
int mf_cid;
void (*mf_prfree)(void *);
void *mf_private;
};
#define MFF_MOUNTED 0x0001
#define MFF_MOUNTING 0x0002
#define MFF_UNMOUNTING 0x0004
#define MFF_RESTART 0x0008
#define MFF_MKMNT 0x0010
#define MFF_ERROR 0x0020
#define MFF_LOGDOWN 0x0040
#define MFF_RSTKEEP 0x0080
#define MFF_WANTTIMO 0x0100
struct am_node {
int am_mapno;
mntfs *am_mnt;
char *am_name;
char *am_path;
char *am_link;
am_node *am_parent,
*am_ysib,
*am_osib,
*am_child;
struct attrstat am_attr;
#define am_fattr am_attr.attrstat_u.attributes
int am_flags;
int am_error;
time_t am_ttl;
int am_timeo_w;
int am_timeo;
unsigned int am_gen;
char *am_pref;
am_stats am_stats;
};
#define AMF_NOTIMEOUT 0x0001
#define AMF_ROOT 0x0002
#define ONE_HOUR (60 * 60)
#define ALLOWED_MOUNT_TIME 40
#define AM_TTL (5 * 60)
#define AM_TTL_W (2 * 60)
#define AM_PINGER 30
#define AFS_TIMEO 8
#define AFS_RETRANS ((ALLOWED_MOUNT_TIME*10+5*afs_timeo)/afs_timeo * 2)
#define RPC_XID_PORTMAP 0
#define RPC_XID_MOUNTD 1
#define RPC_XID_NFSPING 2
#define RPC_XID_MASK (0x0f)
#define MK_RPC_XID(type_id, uniq) ((type_id) | ((uniq) << 4))