// -*-c++-*-
/* $Id: sfsmisc.h,v 1.50 2001/10/31 21:43:17 dm Exp $ */

/*
 *
 * Copyright (C) 1999 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_H_
#define _SFSMISC_H_ 1

#include "nfs3_prot.h"
#include "sfs_prot.h"
#include "amisc.h"

struct svccb;
struct aclnt;
struct asrv;
struct rabin_priv;
struct axprt_crypt;

/* nfs3_err.C */
extern void nfs3_err (svccb *sbp, nfsstat3 status);
extern void nfs3exp_err (svccb *sbp, nfsstat3 status);
const strbuf &strbuf_cat (const strbuf &sb, nfsstat3 err);

/* sfspath.C */
enum { ascii_hostid_len = (sizeof (sfs_hash) * 8 + 4) / 5 };
bool sfs_ascii2hostid (sfs_hash *hid, const char *p);
bool sfsgethost_label (const char *&p);
bool sfsgethost_dotlabel (const char *&p);
str sfsgethost (const char *&p);
bool sfs_parsepath (str path, str *host = NULL,
		    sfs_hash *hostid = NULL, u_int16_t *portp = NULL);
bool sfs_mkhostid (sfs_hash *id, const sfs_hostinfo &info);
bool sfs_ckhostid (const sfs_hash *id, const sfs_hostinfo &info);
bool sfs_ckpath (str sname, const sfs_hostinfo &info);
bool sfs_ckci (const sfs_connectinfo &ci, const sfs_hostinfo &info);
str sfs_hostinfo2path (const sfs_hostinfo &info);
bool sfs_checkrevoke (const sfs_pathrevoke &rev);

/* sfs_err.C */
const strbuf &strbuf_cat (const strbuf &sb, sfsstat err);
const strbuf &strbuf_cat (const strbuf &sb, sfsauth_stat status);

/* sfsconst.C */
extern u_int32_t sfs_release;
extern u_int16_t sfs_port;
extern uid_t sfs_uid;
extern gid_t sfs_gid;
extern uid_t nobody_uid;
extern gid_t nobody_gid;
extern gid_t sfs_resvgid_start;
extern u_int sfs_resvgid_count;
#ifdef MAINTAINER
extern bool runinplace;
#else /* !MAINTAINER */
enum { runinplace = false };
#endif /* !MAINTAINER */
extern const char *sfsroot;
extern str sfsdir;
extern str sfssockdir;
extern str sfsdevdb;
extern const char *etc1dir;
extern const char *etc2dir;
extern const char *etc3dir;
extern u_int sfs_pubkeysize;
extern u_int sfs_minpubkeysize;
extern u_int sfs_maxpubkeysize;
extern u_int sfs_pwdcost;
const u_int sfs_maxpwdcost = 32;
extern u_int sfs_hashcost;
extern u_int sfs_maxhashcost;

void sfsconst_init ();
str sfsconst_etcfile (const char *name);
str sfsconst_etcfile_required (const char *name);
void mksfsdir (str path, mode_t mode,
	       struct stat *sbp = NULL, uid_t uid = sfs_uid);

/* sfsaid.C */
extern const bool sfsaid_shift;
typedef u_int64_t sfs_aid;
extern const sfs_aid sfsaid_sfs;
extern const sfs_aid sfsaid_nobody;
bool sfs_specaid (sfs_aid);
sfs_aid sfs_mkaid (u_int32_t uid, u_int32_t gid);
sfs_aid aup2aid (const authunix_parms *aup);
sfs_aid myaid ();

/* suidgetfd.C */
int suidgetfd (str prog);
int suidgetfd_required (str prog);

/* unixserv.C */
struct axprt_unix;
typedef callback<void, ptr<axprt_unix>,
                 const authunix_parms *>::ref suidservcb;
void sfs_unixserv (str sock, cbi cb, mode_t = 0600);
void sfs_suidserv (str prog, suidservcb cb);

/* sfssesskey.C */
inline const sfs_kmsg *
sfs_get_kmsg (const str &s)
{
  return reinterpret_cast<const sfs_kmsg *> (s.cstr ());
}
void sfs_get_sesskey (sfs_hash *ksc, sfs_hash *kcs,
		      const sfs_servinfo &si, const sfs_kmsg *smsg, 
		      const sfs_connectinfo &ci, const bigint &kc,
		      const sfs_kmsg *cmsg);
void sfs_get_sessid (sfs_hash *sessid, const sfs_hash *ksc,
		     const sfs_hash *kcs);
void sfs_get_authid (sfs_hash *authid, sfs_service service, sfs_hostname name,
		     const sfs_hash *hostid, const sfs_hash *sessid);
void sfs_server_crypt (svccb *sbp, rabin_priv *sk,
		       const sfs_connectinfo &ci, const sfs_servinfo &si,
		       sfs_hash *sessid, const sfs_hashcharge &charge,
		       axprt_crypt *cx = NULL);
void sfs_client_crypt (ptr<aclnt> c, ptr<rabin_priv> clntkey,
		       const sfs_connectinfo &ci, const sfs_connectok &cres,
		       callback<void, const sfs_hash *>::ref cb,
		       ptr<axprt_crypt> cx = NULL);

#include "keyfunc.h"

template<> struct hashfn<vec<str> > {
  hashfn () {}
  hash_t operator() (const vec<str> &v) const {
    u_int val = HASHSEED;
    for (const str *sp = v.base (); sp < v.lim (); sp++)
      val = hash_bytes (sp->cstr (), sp->len (), val);
    return val;
  }
};
template<> struct equals<vec<str> > {
  equals () {}
  bool operator() (const vec<str> &a, const vec<str> &b) const {
    size_t n = a.size ();
    if (n != b.size ())
      return false;
    while (n-- > 0)
      if (a[n] != b[n])
	return false;
    return true;
  }
};

/* sfssesskey.C */
int path2sch (str path, str *sch);

#endif /* _SFSMISC_H_ */
