/* Copyright (C) 1998, 1999 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@suse.de>

   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 __NISD_H__
#define __NISD_H__

#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#else
#include "cdefs.h"
#endif

#ifdef HAVE_PATHS_H
#include <paths.h>
#endif

#include "nis_db.h"

#ifndef _PATH_VARRUN
#define _PATH_VARRUN "/etc/"
#endif
#ifndef _PATH_NIS
#define _PATH_NIS "/var/nis"
#endif
#ifndef _PATH_NIS_DATA
#define _PATH_NIS_DATA _PATH_NIS"/data"
#endif
#ifndef _NIS_CATALOG
#define _NIS_CATALOG "../data.dict"
#endif
#ifndef _PATH_NIS_TRANS_LOG
#define _PATH_NIS_TRANS_LOG _PATH_NIS"/trans.log"
#endif
#ifndef _PATH_NIS_ROOT_OBJ
#define _PATH_NIS_ROOT_OBJ _PATH_NIS_DATA"/root.object"
#endif
#ifndef _PATH_NIS_SRVLIST
#define _PATH_NIS_SRVLIST _PATH_NIS_DATA"/serving_list"
#endif

#define CLIENT_CLOCK    &ct
#define SERVER_CLOCK    &zt
#define CACHE_CLOCK     &at
#define DATABASE_CLOCK  &dt

#define CLIENT_CLOCK_DECLS      struct timeval ct = { 0, 0 }
#define SERVER_CLOCK_DECLS      struct timeval zt = { 0, 0 }
#define CACHE_CLOCK_DECLS       struct timeval at = { 0, 0 }
#define DATABASE_CLOCK_DECLS    struct timeval dt = { 0, 0 }

extern int start_clock(struct timeval *);
extern unsigned long stop_clock(struct timeval *);

extern int verbose;
extern int securelevel;
extern int readonly;
extern time_t boottime;
extern nis_object *root_obj;
extern nis_object *parent_obj;

extern bool_t nis_lookup_3_r (ns_request *, nis_result *, struct svc_req *);
extern bool_t nis_add_3_r (ns_request *, nis_result *, struct svc_req *);
extern bool_t nis_modify_3_r (ns_request *, nis_result *, struct svc_req *);
extern bool_t nis_remove_3_r (ns_request *, nis_result *, struct svc_req *);
extern bool_t nis_iblist_3_r (ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_ibadd_3_r (ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_ibmodify_3_r (ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_ibremove_3_r(ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_ibfirst_3_r(ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_ibnext_3_r(ib_request *, nis_result *, struct svc_req *);
extern bool_t nis_finddirectory_3_r(fd_args *, fd_result *, struct svc_req *);
extern bool_t nis_status_3_r(nis_taglist *, nis_taglist *, struct svc_req *);
extern bool_t
nis_dumplog_3_r(dump_args *argp, log_result *result, struct svc_req *rqstp);
extern bool_t
nis_dump_3_r(dump_args *argp, log_result *result, struct svc_req *rqstp);
extern bool_t
nis_callback_3_r(netobj *argp, bool_t *result, struct svc_req *rqstp);
extern bool_t
nis_cptime_3_r(nis_name *argp, uint32_t *result, struct svc_req *rqstp);
extern bool_t
nis_checkpoint_3_r(nis_name *argp, cp_result *result, struct svc_req *rqstp);
extern bool_t
nis_ping_3_r(ping_args *argp, void *result, struct svc_req *rqstp);
extern bool_t
nis_servstate_3_r(nis_taglist *argp, nis_taglist *result, struct svc_req *rqstp);
extern bool_t
nis_mkdir_3_r(nis_name *argp, nis_error *result, struct svc_req *rqstp);
extern bool_t
nis_rmdir_3_r(nis_name *argp, nis_error *result, struct svc_req *rqstp);
extern bool_t
nis_updkeys_3_r(nis_name *argp, nis_error *result, struct svc_req *rqstp);
extern int nis_prog_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);

extern void nis_prog_3 (struct svc_req *, register SVCXPRT *);

/* nisd_stats.c */
extern void nis_init_stats __P ((void));
extern void nis_update_stats __P ((unsigned int, bool_t, unsigned long));
extern void nis_getstate __P ((nis_taglist *, nis_taglist *));
extern nis_error nis_load_srvlist __P ((void));
extern nis_error nis_store_srvlist __P ((void));
extern nis_error add_to_srvlist __P ((const_nis_name name));
extern nis_error remove_from_srvlist __P ((const_nis_name name));
extern bool_t is_in_srvlist __P ((const_nis_name name));

/* access.c */
extern nis_name get_nis_principal __P ((struct svc_req *rqstp));
extern bool_t nis_check_access __P ((uint32_t action, uint32_t perms,
				     const_nis_name princ,
				     const_nis_name owner,
				     const_nis_name group));

/* nisd_lookup.c */
extern bool_t nisd_i_am_replica __P ((directory_obj *dir));
extern nis_result *nisd_lookup __P ((const_nis_name name, unsigned int flags));

/* nisd_db.c */
extern db_status db_create_dir __P ((const_nis_name name));
extern nis_result *db_lookup __P ((const_nis_name name));

/* nisd_cache.c */
#define CHECK_MASTER    1       /* return NIS_NOTMASTER if we are not master */
#define CHECK_SERVER    2       /* return NIS_NOT_ME if we are not server */
#define CACHE_ONLY      4       /* only check cache */
#define LOOKUP_ONLY     8       /* only call nis_lookup(3) */

extern void get_ocache_stats __P ((u_long *hits, u_long *misses,
				   u_long *calls));
extern void get_dcache_stats __P ((u_long *hits, u_long *misses,
				   u_long *calls));
extern nis_error nis_ocache_lookup __P ((nis_name, uint32_t, uint32_t,
					 nis_object **));
extern void nis_ocache_insert __P ((nis_object *obj));
extern nis_error nis_dcache_lookup __P ((nis_name, uint32_t, uint32_t,
					 directory_obj **));
extern void remove_from_cache __P ((const_nis_name name));


#if 0
extern void __nis_ocache_insert __P(( nis_object * ));
extern nis_error __nis_dcache_lookup __P(( nis_name, unsigned long,
                                         unsigned long, directory_obj ** ));
extern void __nis_get_dcache_stats __P(( unsigned long * ,
                                        unsigned long * ,
                                        unsigned long * ));
extern nis_error __nis_flush_dcache __P(( void ));
extern void __nis_flush_one_dir __P(( nis_name ));
#endif

static inline bool_t
nis_can_read (const_nis_name principal, nis_object *obj)
{
  return nis_check_access (NIS_READ_ACC, obj->zo_access,
			   principal, obj->zo_owner, obj->zo_group);
}

static inline bool_t
nis_can_create (const_nis_name principal, nis_object *obj)
{
  return nis_check_access (NIS_CREATE_ACC, obj->zo_access,
			   principal, obj->zo_owner, obj->zo_group);
}

static inline bool_t
nis_can_destroy (const_nis_name principal, nis_object *obj)
{
  return nis_check_access (NIS_DESTROY_ACC, obj->zo_access,
			   principal, obj->zo_owner, obj->zo_group);
}

static inline nis_error
nis_validname (char *name)
{
  if (name == NULL)        /* string pointer shouldn't be NULL */
    return NIS_BADNAME;

  if (strchr (" \t.[],=@+-", name[0]) != NULL)
    return NIS_BADNAME;

  /* No slashes allowed anywhere in an NIS+ name. */
  if (strchr (name, '/') != NULL)
    return NIS_BADNAME;

  /* Name must be fully qualified. */
  if (name[strlen(name) - 1] != '.')
    return NIS_BADNAME;

  return NIS_SUCCESS;
}

static inline nis_error
db2nis_error (db_status status)
{
  switch (status) /* XXX Optimize (look glibc) */
    {
    case DB_SUCCESS:
      return NIS_SUCCESS;
    case DB_NOTFOUND:
      return NIS_NOTFOUND;
    case DB_NOTUNIQUE:
      return NIS_NOTUNIQUE;
    case DB_BADTABLE:
      return NIS_BADNAME;
    case DB_BADQUERY:
      return NIS_BADREQUEST;
    case DB_BADOBJECT:
      return NIS_BADOBJECT;
    case DB_MEMORY_LIMIT:
      return NIS_NOMEMORY;
    case DB_STORAGE_LIMIT:
      return NIS_FAIL;
    case DB_INTERNAL_ERROR:
      return NIS_SYSTEMERROR;
    default:
      return NIS_FAIL;
    }
  return NIS_SYSTEMERROR;
}

#endif
