Blame nss/common.h

Packit 6bd9ab
/*
Packit 6bd9ab
   common.h - common functions for NSS lookups
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2015 Arthur de Jong
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#ifndef NSS__COMMON_H
Packit 6bd9ab
#define NSS__COMMON_H 1
Packit 6bd9ab
Packit 6bd9ab
#include <stdio.h>
Packit 6bd9ab
#include <stdlib.h>
Packit 6bd9ab
Packit 6bd9ab
#include "nslcd.h"
Packit 6bd9ab
#include "common/nslcd-prot.h"
Packit 6bd9ab
#include "compat/attrs.h"
Packit 6bd9ab
#include "compat/nss_compat.h"
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_SOLARIS
Packit 6bd9ab
#include "solnss.h"
Packit 6bd9ab
#endif /* NSS_FLAVOUR_SOLARIS */
Packit 6bd9ab
Packit 6bd9ab
/* If not TLS (thread local storage) is available on the platform
Packit 6bd9ab
   don't use it. This should not be a problem on most platforms because
Packit 6bd9ab
   get*ent() is not expected to be thread-safe (at least not on Glibc). */
Packit 6bd9ab
#ifndef TLS
Packit 6bd9ab
#define TLS
Packit 6bd9ab
#endif /* not TLS */
Packit 6bd9ab
Packit 6bd9ab
/* skip timeout determines the maximum time to wait when closing the
Packit 6bd9ab
   connection and reading whatever data that is available */
Packit 6bd9ab
#define SKIP_TIMEOUT 500
Packit 6bd9ab
Packit 6bd9ab
/* These are macros for handling read and write problems, they are
Packit 6bd9ab
   NSS specific due to the return code so are defined here. They
Packit 6bd9ab
   genrally close the open file, set an error code and return with
Packit 6bd9ab
   an error status. */
Packit 6bd9ab
Packit 6bd9ab
/* Macro is called to handle errors in opening a client connection. */
Packit 6bd9ab
#define ERROR_OUT_OPENERROR                                                 \
Packit 6bd9ab
  *errnop = ENOENT;                                                         \
Packit 6bd9ab
  return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
Packit 6bd9ab
Packit 6bd9ab
/* Macro is called to handle errors on read operations. */
Packit 6bd9ab
#define ERROR_OUT_READERROR(fp)                                             \
Packit 6bd9ab
  (void)tio_close(fp);                                                      \
Packit 6bd9ab
  fp = NULL;                                                                \
Packit 6bd9ab
  *errnop = ENOENT;                                                         \
Packit 6bd9ab
  return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
Packit 6bd9ab
/* Macro is called to handle problems with too small a buffer.
Packit 6bd9ab
   This triggers the caller to call the function with a larger
Packit 6bd9ab
   buffer (see NSS_GETENT below). */
Packit 6bd9ab
#define ERROR_OUT_BUFERROR(fp)                                              \
Packit 6bd9ab
  *errnop = ERANGE;                                                         \
Packit 6bd9ab
  return NSS_STATUS_TRYAGAIN;
Packit 6bd9ab
Packit 6bd9ab
/* This macro is called if there was a problem with a write
Packit 6bd9ab
   operation. */
Packit 6bd9ab
#define ERROR_OUT_WRITEERROR(fp)                                            \
Packit 6bd9ab
  ERROR_OUT_READERROR(fp)
Packit 6bd9ab
Packit 6bd9ab
/* This macro is called if the read status code is not
Packit 6bd9ab
   NSLCD_RESULT_BEGIN. */
Packit 6bd9ab
#define ERROR_OUT_NOSUCCESS(fp)                                             \
Packit 6bd9ab
  (void)tio_close(fp);                                                      \
Packit 6bd9ab
  fp = NULL;                                                                \
Packit 6bd9ab
  return NSS_STATUS_NOTFOUND;
Packit 6bd9ab
Packit 6bd9ab
/* These are some general macros that are used to build parts of the
Packit 6bd9ab
   genral macros below. */
Packit 6bd9ab
Packit 6bd9ab
/* check to see if we should answer NSS requests */
Packit 6bd9ab
#define NSS_AVAILCHECK                                                      \
Packit 6bd9ab
  if (!NSS_NAME(enablelookups))                                             \
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
Packit 6bd9ab
/* extra definitions we need (nothing for Glibc) */
Packit 6bd9ab
#define NSS_EXTRA_DEFS ;
Packit 6bd9ab
Packit 6bd9ab
/* check validity of passed buffer (Glibc flavour) */
Packit 6bd9ab
#define NSS_BUFCHECK                                                        \
Packit 6bd9ab
  if (buffer == NULL)                                                       \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    *errnop = EINVAL;                                                       \
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;                                              \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  if (buflen == 0)                                                          \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    *errnop = ERANGE;                                                       \
Packit 6bd9ab
    return NSS_STATUS_TRYAGAIN;                                             \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
Packit 6bd9ab
/* The following macros to automatically generate get..byname(),
Packit 6bd9ab
   get..bynumber(), setent(), getent() and endent() function
Packit 6bd9ab
   bodies. These functions have very common code so this can
Packit 6bd9ab
   easily be reused. */
Packit 6bd9ab
Packit 6bd9ab
/* This is a generic get..by..() generation macro. The action
Packit 6bd9ab
   parameter is the NSLCD_ACTION_.. action, the writefn is the
Packit 6bd9ab
   operation for writing the parameters and readfn is the function
Packit 6bd9ab
   name for reading a single result entry. The function is assumed
Packit 6bd9ab
   to have result, buffer, buflen and errnop parameters that define
Packit 6bd9ab
   the result structure, the user buffer with length and the
Packit 6bd9ab
   errno to return. This macro should be called through some of
Packit 6bd9ab
   the customized ones below. */
Packit 6bd9ab
#define NSS_GETONE(action, writefn, readfn)                                 \
Packit 6bd9ab
  TFILE *fp;                                                                \
Packit 6bd9ab
  int32_t tmpint32;                                                         \
Packit 6bd9ab
  nss_status_t retv;                                                        \
Packit 6bd9ab
  NSS_EXTRA_DEFS;                                                           \
Packit 6bd9ab
  NSS_AVAILCHECK;                                                           \
Packit 6bd9ab
  NSS_BUFCHECK;                                                             \
Packit 6bd9ab
  /* open socket and write request */                                       \
Packit 6bd9ab
  NSLCD_REQUEST(fp, action, writefn);                                       \
Packit 6bd9ab
  /* read response */                                                       \
Packit 6bd9ab
  READ_RESPONSE_CODE(fp);                                                   \
Packit 6bd9ab
  retv = readfn;                                                            \
Packit 6bd9ab
  /* close socket and we're done */                                         \
Packit 6bd9ab
  if ((retv == NSS_STATUS_SUCCESS) || (retv == NSS_STATUS_TRYAGAIN))        \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    (void)tio_skipall(fp, SKIP_TIMEOUT);                                    \
Packit 6bd9ab
    (void)tio_close(fp);                                                    \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  return retv;
Packit 6bd9ab
Packit 6bd9ab
/* This macro generates a simple setent() function body. This closes any
Packit 6bd9ab
   open streams so that NSS_GETENT() can open a new file. */
Packit 6bd9ab
#define NSS_SETENT(fp)                                                      \
Packit 6bd9ab
  NSS_AVAILCHECK;                                                           \
Packit 6bd9ab
  if (fp != NULL)                                                           \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    (void)tio_close(fp);                                                    \
Packit 6bd9ab
    fp = NULL;                                                              \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
Packit 6bd9ab
/* This macro generates a getent() function body. If the stream is not yet
Packit 6bd9ab
   open, a new one is opened, a request is written and a check is done for
Packit 6bd9ab
   a response header. A single entry is read with the readfn() function. */
Packit 6bd9ab
#define NSS_GETENT(fp, action, readfn)                                      \
Packit 6bd9ab
  int32_t tmpint32;                                                         \
Packit 6bd9ab
  nss_status_t retv;                                                        \
Packit 6bd9ab
  NSS_EXTRA_DEFS;                                                           \
Packit 6bd9ab
  NSS_AVAILCHECK;                                                           \
Packit 6bd9ab
  NSS_BUFCHECK;                                                             \
Packit 6bd9ab
  /* check that we have a valid file descriptor */                          \
Packit 6bd9ab
  if (fp == NULL)                                                           \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    /* open a new stream and write the request */                           \
Packit 6bd9ab
    NSLCD_REQUEST(fp, action, /* no writefn */ ;);                          \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* prepare for buffer errors */                                           \
Packit 6bd9ab
  tio_mark(fp);                                                             \
Packit 6bd9ab
  /* read a response */                                                     \
Packit 6bd9ab
  READ_RESPONSE_CODE(fp);                                                   \
Packit 6bd9ab
  retv = readfn;                                                            \
Packit 6bd9ab
  /* check read result */                                                   \
Packit 6bd9ab
  if (retv == NSS_STATUS_TRYAGAIN)                                          \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    /* if we have a full buffer try to reset the stream */                  \
Packit 6bd9ab
    if (tio_reset(fp))                                                      \
Packit 6bd9ab
    {                                                                       \
Packit 6bd9ab
      /* reset failed, we close and give up with a permanent error          \
Packit 6bd9ab
         because we cannot retry just the getent() call because it          \
Packit 6bd9ab
         may not be only the first entry that failed */                     \
Packit 6bd9ab
      tio_close(fp);                                                        \
Packit 6bd9ab
      fp = NULL;                                                            \
Packit 6bd9ab
      *errnop = EINVAL;                                                     \
Packit 6bd9ab
      return NSS_STATUS_UNAVAIL;                                            \
Packit 6bd9ab
    }                                                                       \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  else if (retv != NSS_STATUS_SUCCESS)                                      \
Packit 6bd9ab
    fp = NULL; /* file should be closed by now */                           \
Packit 6bd9ab
  return retv;
Packit 6bd9ab
Packit 6bd9ab
/* This macro generates an endent() function body. This just closes
Packit 6bd9ab
   the stream. */
Packit 6bd9ab
#define NSS_ENDENT(fp)                                                      \
Packit 6bd9ab
  NSS_AVAILCHECK;                                                           \
Packit 6bd9ab
  if (fp != NULL)                                                           \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    (void)tio_skipall(fp, SKIP_TIMEOUT);                                    \
Packit 6bd9ab
    (void)tio_close(fp);                                                    \
Packit 6bd9ab
    fp = NULL;                                                              \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
Packit 6bd9ab
#endif /* not NSS__COMMON_H */