// -*-c++-*- /* $Id: sfsclient.h,v 1.13 2001/06/28 04:47:23 dm Exp $ */ /* * * Copyright (C) 2000 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #ifndef _SFSMISC_SFSCLIENT_H_ #define _SFSMISC_SFSCLIENT_H_ 1 #include "nfsserv.h" #include "sfsagent.h" #include "vec.h" #include "qhash.h" #include "axprt_crypt.h" struct sfscd_mountarg; class rabin_priv; class sfsprog; template<> struct qhash_lookup_return { typedef AUTH *type; typedef AUTH *const_type; static type ret (auto_auth *a) { if (a) return *a; return NULL; } }; struct sfsserverargs { typedef callback::ref fhcb; ref ns; int fd; sfsprog *p; sfscd_mountarg *ma; fhcb cb; sfsserverargs (ref ns, int fd, sfsprog *p, sfscd_mountarg *ma, fhcb cb) : ns (ns), fd (fd), p (p), ma (ma), cb (cb) {} }; class sfsserver : public virtual refcount { public: typedef callback::ref fhcb; private: bool lock_flag; bool condemn_flag; bool destroyed; int recon_backoff; timecb_t *recon_tmo; void lock () { assert (!lock_flag); lock_flag = true; } void unlock (); void reconnect (); void reconnect_0 (); void reconnect_1 (int fd); void reconnect_2 (ref res, clnt_stat err); void getsessid (const sfs_hash *); void getfsinfo (sfs_fsinfo *fsi, clnt_stat err); void connection_failure (bool permanent = false); void retrootfh (fhcb cb); protected: ref ns; vec waitq; sfsserver (const sfsserverargs &a); virtual ~sfsserver (); void sfsdispatch (svccb *sbp); virtual void setfd (int fd); virtual sfs_fsinfo *fsinfo_alloc () { return New sfs_fsinfo; } virtual void fsinfo_free (sfs_fsinfo *fsi) { delete fsi; } virtual xdrproc_t fsinfo_marshall () { return xdr_sfs_fsinfo; } typedef callback::ref crypt_cb; virtual void crypt (sfs_connectok cres, crypt_cb cb); virtual bool authok (nfscall *) { return true; } virtual void initstate () {} virtual void flushstate () {} virtual void setx (int fd) { x = axprt_stream::alloc (fd); } virtual bool setrootfh (const sfs_fsinfo *fsi) = 0; virtual void dispatch (nfscall *nc) = 0; public: sfsprog &prog; const str path; const sfs_connectinfo carg; const sfs_hostinfo hinfo; sfs_authinfo authinfo; sfs_fsinfo *fsinfo; nfs_fh3 rootfh; time_t lastuse; ptr x; ptr sfsc; ptr sfscbs; ihash_entry pathlink; tailq_entry idlelink; bool condemned () { return condemn_flag; } bool locked () { return lock_flag; } void touch (); void condemn (); void destroy (); void getnfscall (nfscall *nc); virtual AUTH *authof (sfs_aid) { return NULL; } virtual void authclear (sfs_aid) {} }; class sfsserver_auth : public sfsserver { struct userauth : public virtual refcount { const sfs_aid aid; private: const ref sp; vec ncvec; timecb_t *tmo; callbase *cbase; bool aborted; sfsagent_auth_res ares; sfs_loginres sres; sfs_seqno seqno; int ntries; void finish (u_int32_t authno); void aresult (clnt_stat); void sresult (clnt_stat); void timeout (); void sendreq (); public: userauth (sfs_aid aid, const ref &s); ~userauth (); void pushreq (nfscall *nc); void abort (); }; friend class userauth; sfs_seqno seqno; qhash authnos; qhash > authpending; static ptr key; static timecb_t *keytmo; static void keyexpire (); protected: sfsserver_auth (const sfsserverargs &a) : sfsserver (a), seqno (0) {} void setx (int fd) { x = xc = axprt_crypt::alloc (fd); } virtual void crypt (sfs_connectok cres, crypt_cb cb); virtual bool authok (nfscall *); virtual AUTH *authof (sfs_aid aid) { return authnos[aid]; } virtual void flushstate (); public: ptr xc; static void keygen (); virtual void authclear (sfs_aid); }; template void sfsserver_alloc (sfsprog *prog, ref ns, int tcpfd, sfscd_mountarg *ma, sfsserver::fhcb cb) { if (!ma->cres || (ma->carg.civers == 5 && !sfs_parsepath (ma->carg.ci5->sname))) { (*cb) (NULL); // Named protocols intercept here return; } vNew refcounted (sfsserverargs (ns, tcpfd, prog, ma, cb)); } class sfsprog { struct sfsctl { struct fileinfo { const str fspath; const nfs_fh3 fh; fileinfo (sfsserver *s, const nfs_fh3 &fh) : fspath (s->path), fh (fh) {} }; sfsprog *const prog; ptr s; const sfs_aid aid; int32_t pid; struct authunix_parms aup; ihash_entry hlink; ptr fip; sfsctl (ref x, const authunix_parms *aup, sfsprog *p); ~sfsctl (); void setpid (int32_t npid); void dispatch (svccb *sbp); }; friend class sfsctl; ihash2 ctltab; virtual ~sfsprog () { panic ("sfsprog deleted\n"); } virtual void mountcb (svccb *sbp, const nfs_fh3 *fhp); void cddispatch (svccb *sbp); void ctlaccept (ptr x, const authunix_parms *aup); void linkdispatch (nfscall *nc); void tmosched (bool expired = false); public: typedef void (*allocfn_t) (sfsprog *, ref, int, sfscd_mountarg *, sfsserver::fhcb); const allocfn_t newserver; const bool needclose; ref x; ref cdc; ref cds; ref ns; ref nd; ref linkserv; timecb_t *idletmo; ihash pathtab; tailq idleq; sfsprog (ref cdx, allocfn_t f, bool needclose = false); virtual bool intercept (sfsserver *s, nfscall *nc); }; #endif /* _SFSMISC_SFSCLIENT_H_ */