Blame common/nslcd-prot.h

Packit 6bd9ab
/*
Packit 6bd9ab
   nslcd-prot.h - helper macros for reading and writing in protocol streams
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2014 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 COMMON__NSLCD_PROT_H
Packit 6bd9ab
#define COMMON__NSLCD_PROT_H 1
Packit 6bd9ab
Packit 6bd9ab
#include <arpa/inet.h>
Packit 6bd9ab
#include <netinet/in.h>
Packit 6bd9ab
Packit 6bd9ab
#include "tio.h"
Packit 6bd9ab
Packit 6bd9ab
/* If you use these macros you should define the following macros to
Packit 6bd9ab
   handle error conditions (these marcos should clean up and return from the
Packit 6bd9ab
   function):
Packit 6bd9ab
     ERROR_OUT_WRITEERROR(fp)
Packit 6bd9ab
     ERROR_OUT_READERROR(fp)
Packit 6bd9ab
     ERROR_OUT_BUFERROR(fp)
Packit 6bd9ab
     ERROR_OUT_NOSUCCESS(fp) */
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
/* Debugging marcos that can be used to enable detailed protocol logging,
Packit 6bd9ab
   pass -DDEBUG_PROT to do overall protocol debugging, and -DDEBUG_PROT_DUMP
Packit 6bd9ab
   to dump the actual bytestream. */
Packit 6bd9ab
Packit 6bd9ab
#ifdef DEBUG_PROT
Packit 6bd9ab
/* define a debugging macro to output logging */
Packit 6bd9ab
#include <string.h>
Packit 6bd9ab
#include <errno.h>
Packit 6bd9ab
#define DEBUG_PRINT(fmt, arg)                                               \
Packit 6bd9ab
  fprintf(stderr, "%s:%d:%s: " fmt "\n", __FILE__, __LINE__,                \
Packit 6bd9ab
          __PRETTY_FUNCTION__, arg);
Packit 6bd9ab
#else /* DEBUG_PROT */
Packit 6bd9ab
/* define an empty debug macro to disable logging */
Packit 6bd9ab
#define DEBUG_PRINT(fmt, arg)
Packit 6bd9ab
#endif /* not DEBUG_PROT */
Packit 6bd9ab
Packit 6bd9ab
#ifdef DEBUG_PROT_DUMP
Packit 6bd9ab
/* define a debugging macro to output detailed logging */
Packit 6bd9ab
#ifdef HAVE_STDINT_H
Packit 6bd9ab
#include <stdint.h>
Packit 6bd9ab
#endif /* HAVE_STDINT_H */
Packit 6bd9ab
static void debug_dump(const void *ptr, size_t size)
Packit 6bd9ab
{
Packit 6bd9ab
  int i;
Packit 6bd9ab
  for (i = 0; i < size; i++)
Packit 6bd9ab
    fprintf(stderr, " %02x", ((const uint8_t *)ptr)[i]);
Packit 6bd9ab
  fprintf(stderr, "\n");
Packit 6bd9ab
}
Packit 6bd9ab
#define DEBUG_DUMP(ptr, size)                                               \
Packit 6bd9ab
  fprintf(stderr, "%s:%d:%s:", __FILE__, __LINE__, __PRETTY_FUNCTION__);    \
Packit 6bd9ab
  debug_dump(ptr, size);
Packit 6bd9ab
#else /* DEBUG_PROT_DUMP */
Packit 6bd9ab
/* define an empty debug macro to disable logging */
Packit 6bd9ab
#define DEBUG_DUMP(ptr, size)
Packit 6bd9ab
#endif /* not DEBUG_PROT_DUMP */
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
/* WRITE marcos, used for writing data, on write error they will
Packit 6bd9ab
   call the ERROR_OUT_WRITEERROR macro
Packit 6bd9ab
   these macros may require the availability of the following
Packit 6bd9ab
   variables:
Packit 6bd9ab
   int32_t tmpint32; - temporary variable
Packit 6bd9ab
   */
Packit 6bd9ab
Packit 6bd9ab
#define WRITE(fp, ptr, size)                                                \
Packit 6bd9ab
  DEBUG_PRINT("WRITE       : var="__STRING(ptr)" size=%d", (int)size);      \
Packit 6bd9ab
  DEBUG_DUMP(ptr, size);                                                    \
Packit 6bd9ab
  if (tio_write(fp, ptr, (size_t)size))                                     \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    DEBUG_PRINT("WRITE       : var="__STRING(ptr)" error: %s",              \
Packit 6bd9ab
                strerror(errno));                                           \
Packit 6bd9ab
    ERROR_OUT_WRITEERROR(fp);                                               \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
#define WRITE_INT32(fp, i)                                                  \
Packit 6bd9ab
  DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%08x", (int)i);        \
Packit 6bd9ab
  tmpint32 = htonl((int32_t)(i));                                           \
Packit 6bd9ab
  WRITE(fp, &tmpint32, sizeof(int32_t))
Packit 6bd9ab
Packit 6bd9ab
#define WRITE_STRING(fp, str)                                               \
Packit 6bd9ab
  DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"", (str));    \
Packit 6bd9ab
  if ((str) == NULL)                                                        \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    WRITE_INT32(fp, 0);                                                     \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  else                                                                      \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    WRITE_INT32(fp, strlen(str));                                           \
Packit 6bd9ab
    tmpint32 = ntohl(tmpint32);                                             \
Packit 6bd9ab
    if (tmpint32 > 0)                                                       \
Packit 6bd9ab
    {                                                                       \
Packit 6bd9ab
      WRITE(fp, (str), tmpint32);                                           \
Packit 6bd9ab
    }                                                                       \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
#define WRITE_STRINGLIST(fp, arr)                                           \
Packit 6bd9ab
  if ((arr) == NULL)                                                        \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", 0);             \
Packit 6bd9ab
    WRITE_INT32(fp, 0);                                                     \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  else                                                                      \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    /* first determine length of array */                                   \
Packit 6bd9ab
    for (tmp3int32 = 0; (arr)[tmp3int32] != NULL; tmp3int32++)              \
Packit 6bd9ab
      /* noting */ ;                                                        \
Packit 6bd9ab
    /* write number of strings */                                           \
Packit 6bd9ab
    DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
Packit 6bd9ab
    WRITE_INT32(fp, tmp3int32);                                             \
Packit 6bd9ab
    /* write strings */                                                     \
Packit 6bd9ab
    for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++)                 \
Packit 6bd9ab
    {                                                                       \
Packit 6bd9ab
      WRITE_STRING(fp, (arr)[tmp2int32]);                                   \
Packit 6bd9ab
    }                                                                       \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
#define WRITE_STRINGLIST_EXCEPT(fp, arr, not)                               \
Packit 6bd9ab
  /* first determine length of array */                                     \
Packit 6bd9ab
  tmp3int32 = 0;                                                            \
Packit 6bd9ab
  for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++)                \
Packit 6bd9ab
    if (strcmp((arr)[tmp2int32], (not)) != 0)                               \
Packit 6bd9ab
      tmp3int32++;                                                          \
Packit 6bd9ab
  /* write number of strings (mius one because we intend to skip one) */    \
Packit 6bd9ab
  DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32);  \
Packit 6bd9ab
  WRITE_INT32(fp, tmp3int32);                                               \
Packit 6bd9ab
  /* write strings */                                                       \
Packit 6bd9ab
  for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++)                \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    if (strcmp((arr)[tmp2int32], (not)) != 0)                               \
Packit 6bd9ab
    {                                                                       \
Packit 6bd9ab
      WRITE_STRING(fp, (arr)[tmp2int32]);                                   \
Packit 6bd9ab
    }                                                                       \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
/* READ macros, used for reading data, on read error they will
Packit 6bd9ab
   call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
Packit 6bd9ab
   these macros may require the availability of the following
Packit 6bd9ab
   variables:
Packit 6bd9ab
   int32_t tmpint32; - temporary variable
Packit 6bd9ab
   */
Packit 6bd9ab
Packit 6bd9ab
#define READ(fp, ptr, size)                                                 \
Packit 6bd9ab
  if (tio_read(fp, ptr, (size_t)size))                                      \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    DEBUG_PRINT("READ       : var="__STRING(ptr)" error: %s",               \
Packit 6bd9ab
                strerror(errno));                                           \
Packit 6bd9ab
    ERROR_OUT_READERROR(fp);                                                \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  DEBUG_PRINT("READ       : var="__STRING(ptr)" size=%d", (int)(size));     \
Packit 6bd9ab
  DEBUG_DUMP(ptr, size);
Packit 6bd9ab
Packit 6bd9ab
#define READ_INT32(fp, i)                                                   \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  (i) = (int32_t)ntohl(tmpint32);                                           \
Packit 6bd9ab
  DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32==%08x", (int)(i));
Packit 6bd9ab
Packit 6bd9ab
/* read a string in a fixed-size "normal" buffer */
Packit 6bd9ab
#define READ_STRING(fp, buffer)                                             \
Packit 6bd9ab
  /* read the size of the string */                                         \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d", tmpint32);   \
Packit 6bd9ab
  /* check if read would fit */                                             \
Packit 6bd9ab
  if (((size_t)tmpint32) >= sizeof(buffer))                                 \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    /* will not fit */                                                      \
Packit 6bd9ab
    tmpint32 = (tmpint32 - sizeof(buffer)) + 1;                             \
Packit 6bd9ab
    DEBUG_PRINT("READ       : buffer %d bytes too small", tmpint32);        \
Packit 6bd9ab
    ERROR_OUT_BUFERROR(fp);                                                 \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* read string from the stream */                                         \
Packit 6bd9ab
  if (tmpint32 > 0)                                                         \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    READ(fp, buffer, (size_t)tmpint32);                                     \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* null-terminate string in buffer */                                     \
Packit 6bd9ab
  buffer[tmpint32] = '\0';                                                  \
Packit 6bd9ab
  DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"", buffer);
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
/* READ BUF macros that read data into a pre-allocated buffer.
Packit 6bd9ab
   these macros may require the availability of the following
Packit 6bd9ab
   variables:
Packit 6bd9ab
   int32_t tmpint32; - temporary variable
Packit 6bd9ab
   char *buffer;     - pointer to a buffer for reading strings
Packit 6bd9ab
   size_t buflen;    - the size of the buffer
Packit 6bd9ab
   size_t bufptr;    - the current position in the buffer
Packit 6bd9ab
   */
Packit 6bd9ab
Packit 6bd9ab
/* current position in the buffer */
Packit 6bd9ab
#define BUF_CUR                                                             \
Packit 6bd9ab
  (buffer + bufptr)
Packit 6bd9ab
Packit 6bd9ab
/* check that the buffer has sz bytes left in it */
Packit 6bd9ab
#define BUF_CHECK(fp, sz)                                                   \
Packit 6bd9ab
  if ((bufptr + (size_t)(sz)) > buflen)                                     \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    /* will not fit */                                                      \
Packit 6bd9ab
    tmpint32 = bufptr + (sz) - (buflen);                                    \
Packit 6bd9ab
    DEBUG_PRINT("READ       : buffer %d bytes too small", tmpint32);        \
Packit 6bd9ab
    ERROR_OUT_BUFERROR(fp);                                                 \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
/* move the buffer pointer */
Packit 6bd9ab
#define BUF_SKIP(sz)                                                        \
Packit 6bd9ab
  bufptr += (size_t)(sz);
Packit 6bd9ab
Packit 6bd9ab
/* move BUF_CUR foreward so that it is aligned to the specified
Packit 6bd9ab
   type width */
Packit 6bd9ab
#define BUF_ALIGN(fp, type)                                                 \
Packit 6bd9ab
  /* figure out number of bytes to skip foreward */                         \
Packit 6bd9ab
  tmp2int32 = (sizeof(type) - ((BUF_CUR - (char *)NULL) % sizeof(type)))    \
Packit 6bd9ab
              % sizeof(type);                                               \
Packit 6bd9ab
  /* check and skip */                                                      \
Packit 6bd9ab
  BUF_CHECK(fp, tmp2int32);                                                 \
Packit 6bd9ab
  BUF_SKIP(tmp2int32);
Packit 6bd9ab
Packit 6bd9ab
/* allocate a piece of the buffer to store an array in */
Packit 6bd9ab
#define BUF_ALLOC(fp, ptr, type, num)                                       \
Packit 6bd9ab
  /* align to the specified type width */                                   \
Packit 6bd9ab
  BUF_ALIGN(fp, type);                                                      \
Packit 6bd9ab
  /* check that we have enough room */                                      \
Packit 6bd9ab
  BUF_CHECK(fp, (size_t)(num) * sizeof(type));                              \
Packit 6bd9ab
  /* store the pointer */                                                   \
Packit 6bd9ab
  (ptr) = (type *)BUF_CUR;                                                  \
Packit 6bd9ab
  /* reserve the space */                                                   \
Packit 6bd9ab
  BUF_SKIP((size_t)(num) * sizeof(type));
Packit 6bd9ab
Packit 6bd9ab
/* read a binary blob into the buffer */
Packit 6bd9ab
#define READ_BUF(fp, ptr, sz)                                               \
Packit 6bd9ab
  /* check that there is enough room and read */                            \
Packit 6bd9ab
  BUF_CHECK(fp, sz);                                                        \
Packit 6bd9ab
  READ(fp, BUF_CUR, (size_t)sz);                                            \
Packit 6bd9ab
  /* store pointer and skip */                                              \
Packit 6bd9ab
  (ptr) = BUF_CUR;                                                          \
Packit 6bd9ab
  BUF_SKIP(sz);
Packit 6bd9ab
Packit 6bd9ab
/* read string in the buffer (using buffer, buflen and bufptr)
Packit 6bd9ab
   and store the actual location of the string in field */
Packit 6bd9ab
#define READ_BUF_STRING(fp, field)                                          \
Packit 6bd9ab
  /* read the size of the string */                                         \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d", tmpint32); \
Packit 6bd9ab
  /* check if read would fit */                                             \
Packit 6bd9ab
  BUF_CHECK(fp, tmpint32 + 1);                                              \
Packit 6bd9ab
  /* read string from the stream */                                         \
Packit 6bd9ab
  if (tmpint32 > 0)                                                         \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    READ(fp, BUF_CUR, (size_t)tmpint32);                                    \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* null-terminate string in buffer */                                     \
Packit 6bd9ab
  BUF_CUR[tmpint32] = '\0';                                                 \
Packit 6bd9ab
  DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"", BUF_CUR); \
Packit 6bd9ab
  /* prepare result */                                                      \
Packit 6bd9ab
  (field) = BUF_CUR;                                                        \
Packit 6bd9ab
  BUF_SKIP(tmpint32 + 1);
Packit 6bd9ab
Packit 6bd9ab
/* read an array from a stram and store it as a null-terminated
Packit 6bd9ab
   array list (size for the array is allocated) */
Packit 6bd9ab
#define READ_BUF_STRINGLIST(fp, arr)                                        \
Packit 6bd9ab
  /* read the number of entries */                                          \
Packit 6bd9ab
  READ(fp, &tmp3int32, sizeof(int32_t));                                    \
Packit 6bd9ab
  tmp3int32 = ntohl(tmp3int32);                                             \
Packit 6bd9ab
  DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32);   \
Packit 6bd9ab
  /* allocate room for *char[num + 1] */                                      \
Packit 6bd9ab
  BUF_ALLOC(fp, arr, char *, tmp3int32 + 1);                                \
Packit 6bd9ab
  /* read all entries */                                                    \
Packit 6bd9ab
  for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++)                   \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    READ_BUF_STRING(fp, (arr)[tmp2int32]);                                  \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* set last entry to NULL */                                              \
Packit 6bd9ab
  (arr)[tmp2int32] = NULL;
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
/* SKIP macros for skipping over certain parts of the protocol stream. */
Packit 6bd9ab
Packit 6bd9ab
/* skip a number of bytes foreward */
Packit 6bd9ab
#define SKIP(fp, sz)                                                        \
Packit 6bd9ab
  DEBUG_PRINT("READ       : skip %d bytes", (int)(sz));                     \
Packit 6bd9ab
  /* read (skip) the specified number of bytes */                           \
Packit 6bd9ab
  if (tio_skip(fp, sz))                                                     \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    DEBUG_PRINT("READ       : skip error: %s", strerror(errno));            \
Packit 6bd9ab
    ERROR_OUT_READERROR(fp);                                                \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
/* read a string from the stream but don't do anything with the result */
Packit 6bd9ab
#define SKIP_STRING(fp)                                                     \
Packit 6bd9ab
  /* read the size of the string */                                         \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  DEBUG_PRINT("READ_STRING: skip %d bytes", (int)tmpint32);                 \
Packit 6bd9ab
  /* read (skip) the specified number of bytes */                           \
Packit 6bd9ab
  SKIP(fp, tmpint32);
Packit 6bd9ab
Packit 6bd9ab
/* skip a list of strings */
Packit 6bd9ab
#define SKIP_STRINGLIST(fp)                                                 \
Packit 6bd9ab
  /* read the number of entries */                                          \
Packit 6bd9ab
  READ(fp, &tmp3int32, sizeof(int32_t));                                    \
Packit 6bd9ab
  tmp3int32 = ntohl(tmp3int32);                                             \
Packit 6bd9ab
  DEBUG_PRINT("READ_STRLST: skip %d strings", (int)tmp3int32);              \
Packit 6bd9ab
  /* read all entries */                                                    \
Packit 6bd9ab
  for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++)                   \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    SKIP_STRING(fp);                                                        \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
Packit 6bd9ab
/* These are functions and macors for performing common operations in
Packit 6bd9ab
   the nslcd request/response protocol. */
Packit 6bd9ab
Packit 6bd9ab
/* returns a socket to the server or NULL on error (see errno),
Packit 6bd9ab
   socket should be closed with tio_close() */
Packit 6bd9ab
TFILE *nslcd_client_open(void)
Packit 6bd9ab
  MUST_USE;
Packit 6bd9ab
Packit 6bd9ab
/* generic request code */
Packit 6bd9ab
#define NSLCD_REQUEST(fp, action, writefn)                                  \
Packit 6bd9ab
  /* open a client socket */                                                \
Packit 6bd9ab
  if ((fp = nslcd_client_open()) == NULL)                                   \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    ERROR_OUT_OPENERROR;                                                    \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* write a request header with a request code */                          \
Packit 6bd9ab
  WRITE_INT32(fp, (int32_t)NSLCD_VERSION)                                   \
Packit 6bd9ab
  WRITE_INT32(fp, (int32_t)action)                                          \
Packit 6bd9ab
  /* write the request parameters (if any) */                               \
Packit 6bd9ab
  writefn;                                                                  \
Packit 6bd9ab
  /* flush the stream */                                                    \
Packit 6bd9ab
  if (tio_flush(fp) < 0)                                                    \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    DEBUG_PRINT("WRITE_FLUSH : error: %s", strerror(errno));                \
Packit 6bd9ab
    ERROR_OUT_WRITEERROR(fp);                                               \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* read and check response version number */                              \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  if (tmpint32 != (int32_t)NSLCD_VERSION)                                   \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    ERROR_OUT_READERROR(fp);                                                \
Packit 6bd9ab
  }                                                                         \
Packit 6bd9ab
  /* read and check response request number */                              \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  if (tmpint32 != (int32_t)(action))                                        \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    ERROR_OUT_READERROR(fp);                                                \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
/* Read the response code (the result code of the query) from
Packit 6bd9ab
   the stream. */
Packit 6bd9ab
#define READ_RESPONSE_CODE(fp)                                              \
Packit 6bd9ab
  READ(fp, &tmpint32, sizeof(int32_t));                                     \
Packit 6bd9ab
  tmpint32 = ntohl(tmpint32);                                               \
Packit 6bd9ab
  if (tmpint32 != (int32_t)NSLCD_RESULT_BEGIN)                              \
Packit 6bd9ab
  {                                                                         \
Packit 6bd9ab
    ERROR_OUT_NOSUCCESS(fp);                                                \
Packit 6bd9ab
  }
Packit 6bd9ab
Packit 6bd9ab
#endif /* not COMMON__NSLCD_PROT_H */