(root)/
glibc-2.38/
nscd/
nscd-client.h
       1  /* Copyright (c) 1998-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  /* This file defines everything that client code should need to
      19     know to talk to the nscd daemon.  */
      20  
      21  #ifndef _NSCD_CLIENT_H
      22  #define _NSCD_CLIENT_H	1
      23  
      24  #include <stdbool.h>
      25  #include <stdint.h>
      26  #include <string.h>
      27  #include <time.h>
      28  #include <sys/types.h>
      29  #include <atomic.h>
      30  #include <nscd-types.h>
      31  #include <sys/uio.h>
      32  
      33  
      34  /* Version number of the daemon interface */
      35  #define NSCD_VERSION 2
      36  
      37  /* Path of the file where the PID of the running system is stored.  */
      38  #define _PATH_NSCDPID	 "/var/run/nscd/nscd.pid"
      39  
      40  /* Path for the Unix domain socket.  */
      41  #define _PATH_NSCDSOCKET "/var/run/nscd/socket"
      42  
      43  /* Path for the configuration file.  */
      44  #define _PATH_NSCDCONF	 "/etc/nscd.conf"
      45  
      46  /* Maximum allowed length for the key.  */
      47  #define MAXKEYLEN 1024
      48  
      49  
      50  /* Available services.  */
      51  typedef enum
      52  {
      53    GETPWBYNAME,
      54    GETPWBYUID,
      55    GETGRBYNAME,
      56    GETGRBYGID,
      57    GETHOSTBYNAME,
      58    GETHOSTBYNAMEv6,
      59    GETHOSTBYADDR,
      60    GETHOSTBYADDRv6,
      61    SHUTDOWN,		/* Shut the server down.  */
      62    GETSTAT,		/* Get the server statistic.  */
      63    INVALIDATE,           /* Invalidate one special cache.  */
      64    GETFDPW,
      65    GETFDGR,
      66    GETFDHST,
      67    GETAI,
      68    INITGROUPS,
      69    GETSERVBYNAME,
      70    GETSERVBYPORT,
      71    GETFDSERV,
      72    GETNETGRENT,
      73    INNETGR,
      74    GETFDNETGR,
      75    LASTREQ
      76  } request_type;
      77  
      78  
      79  /* Header common to all requests */
      80  typedef struct
      81  {
      82    int32_t version;	/* Version number of the daemon interface.  */
      83    request_type type;	/* Service requested.  */
      84    int32_t key_len;	/* Key length.  */
      85  } request_header;
      86  
      87  
      88  /* Structure sent in reply to password query.  Note that this struct is
      89     sent also if the service is disabled or there is no record found.  */
      90  typedef struct
      91  {
      92    int32_t version;
      93    int32_t found;
      94    nscd_ssize_t pw_name_len;
      95    nscd_ssize_t pw_passwd_len;
      96    uid_t pw_uid;
      97    gid_t pw_gid;
      98    nscd_ssize_t pw_gecos_len;
      99    nscd_ssize_t pw_dir_len;
     100    nscd_ssize_t pw_shell_len;
     101  } pw_response_header;
     102  
     103  
     104  /* Structure sent in reply to group query.  Note that this struct is
     105     sent also if the service is disabled or there is no record found.  */
     106  typedef struct
     107  {
     108    int32_t version;
     109    int32_t found;
     110    nscd_ssize_t gr_name_len;
     111    nscd_ssize_t gr_passwd_len;
     112    gid_t gr_gid;
     113    nscd_ssize_t gr_mem_cnt;
     114  } gr_response_header;
     115  
     116  
     117  /* Structure sent in reply to host query.  Note that this struct is
     118     sent also if the service is disabled or there is no record found.  */
     119  typedef struct
     120  {
     121    int32_t version;
     122    int32_t found;
     123    nscd_ssize_t h_name_len;
     124    nscd_ssize_t h_aliases_cnt;
     125    int32_t h_addrtype;
     126    int32_t h_length;
     127    nscd_ssize_t h_addr_list_cnt;
     128    int32_t error;
     129  } hst_response_header;
     130  
     131  
     132  /* Structure sent in reply to addrinfo query.  Note that this struct is
     133     sent also if the service is disabled or there is no record found.  */
     134  typedef struct
     135  {
     136    int32_t version;
     137    int32_t found;
     138    nscd_ssize_t naddrs;
     139    nscd_ssize_t addrslen;
     140    nscd_ssize_t canonlen;
     141    int32_t error;
     142  } ai_response_header;
     143  
     144  /* Structure filled in by __nscd_getai.  */
     145  struct nscd_ai_result
     146  {
     147    int naddrs;
     148    char *canon;
     149    uint8_t *family;
     150    char *addrs;
     151  };
     152  
     153  /* Structure sent in reply to initgroups query.  Note that this struct is
     154     sent also if the service is disabled or there is no record found.  */
     155  typedef struct
     156  {
     157    int32_t version;
     158    int32_t found;
     159    nscd_ssize_t ngrps;
     160  } initgr_response_header;
     161  
     162  
     163  /* Structure sent in reply to services query.  Note that this struct is
     164     sent also if the service is disabled or there is no record found.  */
     165  typedef struct
     166  {
     167    int32_t version;
     168    int32_t found;
     169    nscd_ssize_t s_name_len;
     170    nscd_ssize_t s_proto_len;
     171    nscd_ssize_t s_aliases_cnt;
     172    int32_t s_port;
     173  } serv_response_header;
     174  
     175  
     176  /* Structure send in reply to netgroup query.  Note that this struct is
     177     sent also if the service is disabled or there is no record found.  */
     178  typedef struct
     179  {
     180    int32_t version;
     181    int32_t found;
     182    nscd_ssize_t nresults;
     183    nscd_ssize_t result_len;
     184  } netgroup_response_header;
     185  
     186  typedef struct
     187  {
     188    int32_t version;
     189    int32_t found;
     190    int32_t result;
     191  } innetgroup_response_header;
     192  
     193  
     194  /* Type for offsets in data part of database.  */
     195  typedef uint32_t ref_t;
     196  /* Value for invalid/no reference.  */
     197  #define ENDREF	UINT32_MAX
     198  
     199  /* Timestamp type.  */
     200  typedef uint64_t nscd_time_t;
     201  
     202  /* Maximum timestamp.  */
     203  #define MAX_TIMEOUT_VALUE \
     204    (sizeof (time_t) == sizeof (long int) ? LONG_MAX : INT_MAX)
     205  
     206  /* Alignment requirement of the beginning of the data region.  */
     207  #define ALIGN 16
     208  
     209  
     210  /* Head of record in data part of database.  */
     211  struct datahead
     212  {
     213    nscd_ssize_t allocsize;	/* Allocated Bytes.  */
     214    nscd_ssize_t recsize;		/* Size of the record.  */
     215    nscd_time_t timeout;		/* Time when this entry becomes invalid.  */
     216    uint8_t notfound;		/* Nonzero if data has not been found.  */
     217    uint8_t nreloads;		/* Reloads without use.  */
     218    uint8_t usable;		/* False if the entry must be ignored.  */
     219    uint8_t unused;		/* Unused.  */
     220    uint32_t ttl;			/* TTL value used.  */
     221  
     222    /* We need to have the following element aligned for the response
     223       header data types and their use in the 'struct dataset' types
     224       defined in the XXXcache.c files.  */
     225    union
     226    {
     227      pw_response_header pwdata;
     228      gr_response_header grdata;
     229      hst_response_header hstdata;
     230      ai_response_header aidata;
     231      initgr_response_header initgrdata;
     232      serv_response_header servdata;
     233      netgroup_response_header netgroupdata;
     234      innetgroup_response_header innetgroupdata;
     235      nscd_ssize_t align1;
     236      nscd_time_t align2;
     237    } data[0];
     238  };
     239  
     240  static inline time_t
     241  datahead_init_common (struct datahead *head, nscd_ssize_t allocsize,
     242  		      nscd_ssize_t recsize, uint32_t ttl)
     243  {
     244    /* Initialize so that we don't write out junk in uninitialized data to the
     245       cache.  */
     246    memset (head, 0, sizeof (*head));
     247  
     248    head->allocsize = allocsize;
     249    head->recsize = recsize;
     250    head->usable = true;
     251  
     252    head->ttl = ttl;
     253  
     254    /* Compute and return the timeout time.  */
     255    return head->timeout = time (NULL) + ttl;
     256  }
     257  
     258  static inline time_t
     259  datahead_init_pos (struct datahead *head, nscd_ssize_t allocsize,
     260  		   nscd_ssize_t recsize, uint8_t nreloads, uint32_t ttl)
     261  {
     262    time_t ret = datahead_init_common (head, allocsize, recsize, ttl);
     263  
     264    head->notfound = false;
     265    head->nreloads = nreloads;
     266  
     267    return ret;
     268  }
     269  
     270  static inline time_t
     271  datahead_init_neg (struct datahead *head, nscd_ssize_t allocsize,
     272  		   nscd_ssize_t recsize, uint32_t ttl)
     273  {
     274    time_t ret = datahead_init_common (head, allocsize, recsize, ttl);
     275  
     276    /* We don't need to touch nreloads here since it is set to our desired value
     277       (0) when we clear the structure.  */
     278    head->notfound = true;
     279  
     280    return ret;
     281  }
     282  
     283  /* Structure for one hash table entry.  */
     284  struct hashentry
     285  {
     286    request_type type:8;		/* Which type of dataset.  */
     287    bool first;			/* True if this was the original key.  */
     288    nscd_ssize_t len;		/* Length of key.  */
     289    ref_t key;			/* Pointer to key.  */
     290    int32_t owner;		/* If secure table, this is the owner.  */
     291    ref_t next;			/* Next entry in this hash bucket list.  */
     292    ref_t packet;			/* Records for the result.  */
     293    union
     294    {
     295      struct hashentry *dellist;	/* Next record to be deleted.  This can be a
     296  				   pointer since only nscd uses this field.  */
     297      ref_t *prevp;		/* Pointer to field containing forward
     298  				   reference.  */
     299    };
     300  };
     301  
     302  
     303  /* Current persistent database version.  */
     304  #define DB_VERSION	2
     305  
     306  /* Maximum time allowed between updates of the timestamp.  */
     307  #define MAPPING_TIMEOUT (5 * 60)
     308  
     309  
     310  /* Used indices for the EXTRA_DATA element of 'database_pers_head'.
     311     Each database has its own indices.  */
     312  #define NSCD_HST_IDX_CONF_TIMESTAMP	0
     313  
     314  
     315  /* Header of persistent database file.  */
     316  struct database_pers_head
     317  {
     318    int32_t version;
     319    int32_t header_size;
     320    volatile int32_t gc_cycle;
     321    volatile int32_t nscd_certainly_running;
     322    volatile nscd_time_t timestamp;
     323    /* Room for extensions.  */
     324    volatile uint32_t extra_data[4];
     325  
     326    nscd_ssize_t module;
     327    nscd_ssize_t data_size;
     328  
     329    nscd_ssize_t first_free;	/* Offset of first free byte in data area.  */
     330  
     331    nscd_ssize_t nentries;
     332    nscd_ssize_t maxnentries;
     333    nscd_ssize_t maxnsearched;
     334  
     335    uint64_t poshit;
     336    uint64_t neghit;
     337    uint64_t posmiss;
     338    uint64_t negmiss;
     339  
     340    uint64_t rdlockdelayed;
     341    uint64_t wrlockdelayed;
     342  
     343    uint64_t addfailed;
     344  
     345    ref_t array[0];
     346  };
     347  
     348  
     349  /* Mapped database record.  */
     350  struct mapped_database
     351  {
     352    const struct database_pers_head *head;
     353    const char *data;
     354    size_t mapsize;
     355    int counter;		/* > 0 indicates it is usable.  */
     356    size_t datasize;
     357  };
     358  #define NO_MAPPING ((struct mapped_database *) -1l)
     359  
     360  struct locked_map_ptr
     361  {
     362    int lock;
     363    struct mapped_database *mapped;
     364  };
     365  #define libc_locked_map_ptr(class, name) class struct locked_map_ptr name
     366  
     367  /* Try acquiring lock for mapptr, returns true if it succeeds, false
     368     if not.  */
     369  static inline bool
     370  __nscd_acquire_maplock (volatile struct locked_map_ptr *mapptr)
     371  {
     372    int cnt = 0;
     373    while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
     374  								1, 0) != 0, 0))
     375      {
     376        // XXX Best number of rounds?
     377        if (__glibc_unlikely (++cnt > 5))
     378  	return false;
     379  
     380        atomic_spin_nop ();
     381      }
     382  
     383    return true;
     384  }
     385  
     386  
     387  /* Open socket connection to nscd server.  */
     388  extern int __nscd_open_socket (const char *key, size_t keylen,
     389  			       request_type type, void *response,
     390  			       size_t responselen) attribute_hidden;
     391  
     392  /* Try to get a file descriptor for the shared memory segment
     393     containing the database.  */
     394  extern struct mapped_database *__nscd_get_mapping (request_type type,
     395  						   const char *key,
     396  						   struct mapped_database **mappedp) attribute_hidden;
     397  
     398  /* Get reference of mapping.  */
     399  extern struct mapped_database *__nscd_get_map_ref (request_type type,
     400  						   const char *name,
     401  						   volatile struct locked_map_ptr *mapptr,
     402  						   int *gc_cyclep)
     403    attribute_hidden;
     404  
     405  /* Unmap database.  */
     406  extern void __nscd_unmap (struct mapped_database *mapped)
     407    attribute_hidden;
     408  
     409  /* Drop reference of mapping.  */
     410  static int
     411  __attribute__ ((unused))
     412  __nscd_drop_map_ref (struct mapped_database *map, int *gc_cycle)
     413  {
     414    if (map != NO_MAPPING)
     415      {
     416        int now_cycle = map->head->gc_cycle;
     417        if (__glibc_unlikely (now_cycle != *gc_cycle))
     418  	{
     419  	  /* We might have read inconsistent data.  */
     420  	  *gc_cycle = now_cycle;
     421  	  return -1;
     422  	}
     423  
     424        if (atomic_fetch_add_relaxed (&map->counter, -1) == 1)
     425  	__nscd_unmap (map);
     426      }
     427  
     428    return 0;
     429  }
     430  
     431  
     432  /* Search the mapped database.  */
     433  extern struct datahead *__nscd_cache_search (request_type type,
     434  					     const char *key,
     435  					     size_t keylen,
     436  					     const struct mapped_database *mapped,
     437  					     size_t datalen)
     438    attribute_hidden;
     439  
     440  /* Wrappers around read, readv and write that only read/write less than LEN
     441     bytes on error or EOF.  */
     442  extern ssize_t __readall (int fd, void *buf, size_t len)
     443    attribute_hidden;
     444  extern ssize_t __readvall (int fd, const struct iovec *iov, int iovcnt)
     445    attribute_hidden;
     446  extern ssize_t writeall (int fd, const void *buf, size_t len)
     447    attribute_hidden;
     448  
     449  /* Get netlink timestamp counter from mapped area or zero.  */
     450  extern uint32_t __nscd_get_nl_timestamp (void)
     451    attribute_hidden;
     452  
     453  #endif /* nscd.h */