Blame nscd/nscd-client.h

Packit 6c4009
/* Copyright (c) 1998-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* This file defines everything that client code should need to
Packit 6c4009
   know to talk to the nscd daemon.  */
Packit 6c4009
Packit 6c4009
#ifndef _NSCD_CLIENT_H
Packit 6c4009
#define _NSCD_CLIENT_H	1
Packit 6c4009
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <stdint.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <time.h>
Packit 6c4009
#include <sys/types.h>
Packit 6c4009
#include <atomic.h>
Packit 6c4009
#include <nscd-types.h>
Packit 6c4009
#include <sys/uio.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Version number of the daemon interface */
Packit 6c4009
#define NSCD_VERSION 2
Packit 6c4009
Packit 6c4009
/* Path of the file where the PID of the running system is stored.  */
Packit 6c4009
#define _PATH_NSCDPID	 "/var/run/nscd/nscd.pid"
Packit 6c4009
Packit 6c4009
/* Path for the Unix domain socket.  */
Packit 6c4009
#define _PATH_NSCDSOCKET "/var/run/nscd/socket"
Packit 6c4009
Packit 6c4009
/* Path for the configuration file.  */
Packit 6c4009
#define _PATH_NSCDCONF	 "/etc/nscd.conf"
Packit 6c4009
Packit 6c4009
/* Maximum allowed length for the key.  */
Packit 6c4009
#define MAXKEYLEN 1024
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Available services.  */
Packit 6c4009
typedef enum
Packit 6c4009
{
Packit 6c4009
  GETPWBYNAME,
Packit 6c4009
  GETPWBYUID,
Packit 6c4009
  GETGRBYNAME,
Packit 6c4009
  GETGRBYGID,
Packit 6c4009
  GETHOSTBYNAME,
Packit 6c4009
  GETHOSTBYNAMEv6,
Packit 6c4009
  GETHOSTBYADDR,
Packit 6c4009
  GETHOSTBYADDRv6,
Packit 6c4009
  SHUTDOWN,		/* Shut the server down.  */
Packit 6c4009
  GETSTAT,		/* Get the server statistic.  */
Packit 6c4009
  INVALIDATE,           /* Invalidate one special cache.  */
Packit 6c4009
  GETFDPW,
Packit 6c4009
  GETFDGR,
Packit 6c4009
  GETFDHST,
Packit 6c4009
  GETAI,
Packit 6c4009
  INITGROUPS,
Packit 6c4009
  GETSERVBYNAME,
Packit 6c4009
  GETSERVBYPORT,
Packit 6c4009
  GETFDSERV,
Packit 6c4009
  GETNETGRENT,
Packit 6c4009
  INNETGR,
Packit 6c4009
  GETFDNETGR,
Packit 6c4009
  LASTREQ
Packit 6c4009
} request_type;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Header common to all requests */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;	/* Version number of the daemon interface.  */
Packit 6c4009
  request_type type;	/* Service requested.  */
Packit 6c4009
  int32_t key_len;	/* Key length.  */
Packit 6c4009
} request_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to password query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t pw_name_len;
Packit 6c4009
  nscd_ssize_t pw_passwd_len;
Packit 6c4009
  uid_t pw_uid;
Packit 6c4009
  gid_t pw_gid;
Packit 6c4009
  nscd_ssize_t pw_gecos_len;
Packit 6c4009
  nscd_ssize_t pw_dir_len;
Packit 6c4009
  nscd_ssize_t pw_shell_len;
Packit 6c4009
} pw_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to group query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t gr_name_len;
Packit 6c4009
  nscd_ssize_t gr_passwd_len;
Packit 6c4009
  gid_t gr_gid;
Packit 6c4009
  nscd_ssize_t gr_mem_cnt;
Packit 6c4009
} gr_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to host query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t h_name_len;
Packit 6c4009
  nscd_ssize_t h_aliases_cnt;
Packit 6c4009
  int32_t h_addrtype;
Packit 6c4009
  int32_t h_length;
Packit 6c4009
  nscd_ssize_t h_addr_list_cnt;
Packit 6c4009
  int32_t error;
Packit 6c4009
} hst_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to addrinfo query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t naddrs;
Packit 6c4009
  nscd_ssize_t addrslen;
Packit 6c4009
  nscd_ssize_t canonlen;
Packit 6c4009
  int32_t error;
Packit 6c4009
} ai_response_header;
Packit 6c4009
Packit 6c4009
/* Structure filled in by __nscd_getai.  */
Packit 6c4009
struct nscd_ai_result
Packit 6c4009
{
Packit 6c4009
  int naddrs;
Packit 6c4009
  char *canon;
Packit 6c4009
  uint8_t *family;
Packit 6c4009
  char *addrs;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to initgroups query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t ngrps;
Packit 6c4009
} initgr_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure sent in reply to services query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t s_name_len;
Packit 6c4009
  nscd_ssize_t s_proto_len;
Packit 6c4009
  nscd_ssize_t s_aliases_cnt;
Packit 6c4009
  int32_t s_port;
Packit 6c4009
} serv_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Structure send in reply to netgroup query.  Note that this struct is
Packit 6c4009
   sent also if the service is disabled or there is no record found.  */
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  nscd_ssize_t nresults;
Packit 6c4009
  nscd_ssize_t result_len;
Packit 6c4009
} netgroup_response_header;
Packit 6c4009
Packit 6c4009
typedef struct
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t found;
Packit 6c4009
  int32_t result;
Packit 6c4009
} innetgroup_response_header;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Type for offsets in data part of database.  */
Packit 6c4009
typedef uint32_t ref_t;
Packit 6c4009
/* Value for invalid/no reference.  */
Packit 6c4009
#define ENDREF	UINT32_MAX
Packit 6c4009
Packit 6c4009
/* Timestamp type.  */
Packit 6c4009
typedef uint64_t nscd_time_t;
Packit 6c4009
Packit 6c4009
/* Maximum timestamp.  */
Packit 6c4009
#define MAX_TIMEOUT_VALUE \
Packit 6c4009
  (sizeof (time_t) == sizeof (long int) ? LONG_MAX : INT_MAX)
Packit 6c4009
Packit 6c4009
/* Alignment requirement of the beginning of the data region.  */
Packit 6c4009
#define ALIGN 16
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Head of record in data part of database.  */
Packit 6c4009
struct datahead
Packit 6c4009
{
Packit 6c4009
  nscd_ssize_t allocsize;	/* Allocated Bytes.  */
Packit 6c4009
  nscd_ssize_t recsize;		/* Size of the record.  */
Packit 6c4009
  nscd_time_t timeout;		/* Time when this entry becomes invalid.  */
Packit 6c4009
  uint8_t notfound;		/* Nonzero if data has not been found.  */
Packit 6c4009
  uint8_t nreloads;		/* Reloads without use.  */
Packit 6c4009
  uint8_t usable;		/* False if the entry must be ignored.  */
Packit 6c4009
  uint8_t unused;		/* Unused.  */
Packit 6c4009
  uint32_t ttl;			/* TTL value used.  */
Packit 6c4009
Packit 6c4009
  /* We need to have the following element aligned for the response
Packit 6c4009
     header data types and their use in the 'struct dataset' types
Packit 6c4009
     defined in the XXXcache.c files.  */
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    pw_response_header pwdata;
Packit 6c4009
    gr_response_header grdata;
Packit 6c4009
    hst_response_header hstdata;
Packit 6c4009
    ai_response_header aidata;
Packit 6c4009
    initgr_response_header initgrdata;
Packit 6c4009
    serv_response_header servdata;
Packit 6c4009
    netgroup_response_header netgroupdata;
Packit 6c4009
    innetgroup_response_header innetgroupdata;
Packit 6c4009
    nscd_ssize_t align1;
Packit 6c4009
    nscd_time_t align2;
Packit 6c4009
  } data[0];
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static inline time_t
Packit 6c4009
datahead_init_common (struct datahead *head, nscd_ssize_t allocsize,
Packit 6c4009
		      nscd_ssize_t recsize, uint32_t ttl)
Packit 6c4009
{
Packit 6c4009
  /* Initialize so that we don't write out junk in uninitialized data to the
Packit 6c4009
     cache.  */
Packit 6c4009
  memset (head, 0, sizeof (*head));
Packit 6c4009
Packit 6c4009
  head->allocsize = allocsize;
Packit 6c4009
  head->recsize = recsize;
Packit 6c4009
  head->usable = true;
Packit 6c4009
Packit 6c4009
  head->ttl = ttl;
Packit 6c4009
Packit 6c4009
  /* Compute and return the timeout time.  */
Packit 6c4009
  return head->timeout = time (NULL) + ttl;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static inline time_t
Packit 6c4009
datahead_init_pos (struct datahead *head, nscd_ssize_t allocsize,
Packit 6c4009
		   nscd_ssize_t recsize, uint8_t nreloads, uint32_t ttl)
Packit 6c4009
{
Packit 6c4009
  time_t ret = datahead_init_common (head, allocsize, recsize, ttl);
Packit 6c4009
Packit 6c4009
  head->notfound = false;
Packit 6c4009
  head->nreloads = nreloads;
Packit 6c4009
Packit 6c4009
  return ret;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static inline time_t
Packit 6c4009
datahead_init_neg (struct datahead *head, nscd_ssize_t allocsize,
Packit 6c4009
		   nscd_ssize_t recsize, uint32_t ttl)
Packit 6c4009
{
Packit 6c4009
  time_t ret = datahead_init_common (head, allocsize, recsize, ttl);
Packit 6c4009
Packit 6c4009
  /* We don't need to touch nreloads here since it is set to our desired value
Packit 6c4009
     (0) when we clear the structure.  */
Packit 6c4009
  head->notfound = true;
Packit 6c4009
Packit 6c4009
  return ret;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Structure for one hash table entry.  */
Packit 6c4009
struct hashentry
Packit 6c4009
{
Packit 6c4009
  request_type type:8;		/* Which type of dataset.  */
Packit 6c4009
  bool first;			/* True if this was the original key.  */
Packit 6c4009
  nscd_ssize_t len;		/* Length of key.  */
Packit 6c4009
  ref_t key;			/* Pointer to key.  */
Packit 6c4009
  int32_t owner;		/* If secure table, this is the owner.  */
Packit 6c4009
  ref_t next;			/* Next entry in this hash bucket list.  */
Packit 6c4009
  ref_t packet;			/* Records for the result.  */
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    struct hashentry *dellist;	/* Next record to be deleted.  This can be a
Packit 6c4009
				   pointer since only nscd uses this field.  */
Packit 6c4009
    ref_t *prevp;		/* Pointer to field containing forward
Packit 6c4009
				   reference.  */
Packit 6c4009
  };
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Current persistent database version.  */
Packit 6c4009
#define DB_VERSION	2
Packit 6c4009
Packit 6c4009
/* Maximum time allowed between updates of the timestamp.  */
Packit 6c4009
#define MAPPING_TIMEOUT (5 * 60)
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Used indices for the EXTRA_DATA element of 'database_pers_head'.
Packit 6c4009
   Each database has its own indices.  */
Packit 6c4009
#define NSCD_HST_IDX_CONF_TIMESTAMP	0
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Header of persistent database file.  */
Packit 6c4009
struct database_pers_head
Packit 6c4009
{
Packit 6c4009
  int32_t version;
Packit 6c4009
  int32_t header_size;
Packit 6c4009
  volatile int32_t gc_cycle;
Packit 6c4009
  volatile int32_t nscd_certainly_running;
Packit 6c4009
  volatile nscd_time_t timestamp;
Packit 6c4009
  /* Room for extensions.  */
Packit 6c4009
  volatile uint32_t extra_data[4];
Packit 6c4009
Packit 6c4009
  nscd_ssize_t module;
Packit 6c4009
  nscd_ssize_t data_size;
Packit 6c4009
Packit 6c4009
  nscd_ssize_t first_free;	/* Offset of first free byte in data area.  */
Packit 6c4009
Packit 6c4009
  nscd_ssize_t nentries;
Packit 6c4009
  nscd_ssize_t maxnentries;
Packit 6c4009
  nscd_ssize_t maxnsearched;
Packit 6c4009
Packit 6c4009
  uint64_t poshit;
Packit 6c4009
  uint64_t neghit;
Packit 6c4009
  uint64_t posmiss;
Packit 6c4009
  uint64_t negmiss;
Packit 6c4009
Packit 6c4009
  uint64_t rdlockdelayed;
Packit 6c4009
  uint64_t wrlockdelayed;
Packit 6c4009
Packit 6c4009
  uint64_t addfailed;
Packit 6c4009
Packit 6c4009
  ref_t array[0];
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Mapped database record.  */
Packit 6c4009
struct mapped_database
Packit 6c4009
{
Packit 6c4009
  const struct database_pers_head *head;
Packit 6c4009
  const char *data;
Packit 6c4009
  size_t mapsize;
Packit 6c4009
  int counter;		/* > 0 indicates it is usable.  */
Packit 6c4009
  size_t datasize;
Packit 6c4009
};
Packit 6c4009
#define NO_MAPPING ((struct mapped_database *) -1l)
Packit 6c4009
Packit 6c4009
struct locked_map_ptr
Packit 6c4009
{
Packit 6c4009
  int lock;
Packit 6c4009
  struct mapped_database *mapped;
Packit 6c4009
};
Packit 6c4009
#define libc_locked_map_ptr(class, name) class struct locked_map_ptr name
Packit 6c4009
Packit 6c4009
/* Try acquiring lock for mapptr, returns true if it succeeds, false
Packit 6c4009
   if not.  */
Packit 6c4009
static inline bool
Packit 6c4009
__nscd_acquire_maplock (volatile struct locked_map_ptr *mapptr)
Packit 6c4009
{
Packit 6c4009
  int cnt = 0;
Packit 6c4009
  while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
Packit 6c4009
								1, 0) != 0, 0))
Packit 6c4009
    {
Packit 6c4009
      // XXX Best number of rounds?
Packit 6c4009
      if (__glibc_unlikely (++cnt > 5))
Packit 6c4009
	return false;
Packit 6c4009
Packit 6c4009
      atomic_spin_nop ();
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return true;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Open socket connection to nscd server.  */
Packit 6c4009
extern int __nscd_open_socket (const char *key, size_t keylen,
Packit 6c4009
			       request_type type, void *response,
Packit 6c4009
			       size_t responselen) attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Try to get a file descriptor for the shared meory segment
Packit 6c4009
   containing the database.  */
Packit 6c4009
extern struct mapped_database *__nscd_get_mapping (request_type type,
Packit 6c4009
						   const char *key,
Packit 6c4009
						   struct mapped_database **mappedp) attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Get reference of mapping.  */
Packit 6c4009
extern struct mapped_database *__nscd_get_map_ref (request_type type,
Packit 6c4009
						   const char *name,
Packit 6c4009
						   volatile struct locked_map_ptr *mapptr,
Packit 6c4009
						   int *gc_cyclep)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Unmap database.  */
Packit 6c4009
extern void __nscd_unmap (struct mapped_database *mapped)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Drop reference of mapping.  */
Packit 6c4009
static int
Packit 6c4009
__attribute__ ((unused))
Packit 6c4009
__nscd_drop_map_ref (struct mapped_database *map, int *gc_cycle)
Packit 6c4009
{
Packit 6c4009
  if (map != NO_MAPPING)
Packit 6c4009
    {
Packit 6c4009
      int now_cycle = map->head->gc_cycle;
Packit 6c4009
      if (__glibc_unlikely (now_cycle != *gc_cycle))
Packit 6c4009
	{
Packit 6c4009
	  /* We might have read inconsistent data.  */
Packit 6c4009
	  *gc_cycle = now_cycle;
Packit 6c4009
	  return -1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (atomic_decrement_val (&map->counter) == 0)
Packit 6c4009
	__nscd_unmap (map);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Search the mapped database.  */
Packit 6c4009
extern struct datahead *__nscd_cache_search (request_type type,
Packit 6c4009
					     const char *key,
Packit 6c4009
					     size_t keylen,
Packit 6c4009
					     const struct mapped_database *mapped,
Packit 6c4009
					     size_t datalen)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Wrappers around read, readv and write that only read/write less than LEN
Packit 6c4009
   bytes on error or EOF.  */
Packit 6c4009
extern ssize_t __readall (int fd, void *buf, size_t len)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
extern ssize_t __readvall (int fd, const struct iovec *iov, int iovcnt)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
extern ssize_t writeall (int fd, const void *buf, size_t len)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Get netlink timestamp counter from mapped area or zero.  */
Packit 6c4009
extern uint32_t __nscd_get_nl_timestamp (void)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
#endif /* nscd.h */