-These files were pulled from the nss-pam-ldapd project version 0.8.12.
+These files were pulled from the nss-pam-ldapd project version 0.9.4.
Copyright notices are in the individual files.
This is not the full distribution of nss-pam-ldapd, and does not
installed, make sure the versions match the version number
shown above. Otherwise, there may be incompatible differences in
the protocols being used. Currently nssov requires at least
-version 0.8.11. If your system's version is older, you will need
+version 0.9.0. If your system's version is older, you will need
to install the client-side stubs from source.
/*
attrs.h - wrapper macros for the gcc __attribute__(()) directive
- Copyright (C) 2007, 2008 Arthur de Jong
+ Copyright (C) 2007, 2008, 2012 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
#define COMPAT__ATTRS_H 1
/* macro for testing the version of GCC */
-#define GCC_VERSION(major,minor) \
+#define GCC_VERSION(major, minor) \
((__GNUC__ > (major)) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
/* These are macros to use some gcc-specific flags in case the're available
/* this is used to flag function parameters that are not used in the function
body. */
-#if GCC_VERSION(3,0)
+#if GCC_VERSION(3, 0)
#define UNUSED(x) x __attribute__((__unused__))
#else
#define UNUSED(x) x
/* this is used to add extra format checking to the function calls as if this
was a printf()-like function */
-#if GCC_VERSION(3,0)
-#define LIKE_PRINTF(format_idx,arg_idx) \
- __attribute__((__format__(__printf__,format_idx,arg_idx)))
+#if GCC_VERSION(3, 0)
+#define LIKE_PRINTF(format_idx, arg_idx) \
+ __attribute__((__format__(__printf__, format_idx, arg_idx)))
#else
-#define LIKE_PRINTF(format_idx,arg_idx) /* no attribute */
+#define LIKE_PRINTF(format_idx, arg_idx) /* no attribute */
#endif
-/* indicates that the function is "pure": it's result is purely based on
+/* indicates that the function is "pure": its result is purely based on
the parameters and has no side effects or used static data */
-#if GCC_VERSION(3,0)
+#if GCC_VERSION(3, 0)
#define PURE __attribute__((__pure__))
#else
#define PURE /* no attribute */
/* the function returns a new data structure that has been freshly
allocated */
-#if GCC_VERSION(3,0)
+#if GCC_VERSION(3, 0)
#define LIKE_MALLOC __attribute__((__malloc__))
#else
#define LIKE_MALLOC /* no attribute */
#endif
/* the function's return value should be used by the caller */
-#if GCC_VERSION(3,4)
+#if GCC_VERSION(3, 4)
#define MUST_USE __attribute__((__warn_unused_result__))
#else
#define MUST_USE /* no attribute */
#endif
/* the function's return value should be used by the caller */
-#if GCC_VERSION(2,5)
+#if GCC_VERSION(2, 5)
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN /* no attribute */
nslcd-prot.h - helper macros for reading and writing in protocol streams
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2009 Arthur de Jong
+ Copyright (C) 2006-2014 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
#ifndef COMMON__NSLCD_PROT_H
#define COMMON__NSLCD_PROT_H 1
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
#include "tio.h"
/* If you use these macros you should define the following macros to
/* define a debugging macro to output logging */
#include <string.h>
#include <errno.h>
-#define DEBUG_PRINT(fmt,arg) \
- fprintf(stderr,"%s:%d:%s: " fmt "\n",__FILE__,__LINE__,__PRETTY_FUNCTION__,arg);
+#define DEBUG_PRINT(fmt, arg) \
+ fprintf(stderr, "%s:%d:%s: " fmt "\n", __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__, arg);
#else /* DEBUG_PROT */
/* define an empty debug macro to disable logging */
-#define DEBUG_PRINT(fmt,arg)
+#define DEBUG_PRINT(fmt, arg)
#endif /* not DEBUG_PROT */
#ifdef DEBUG_PROT_DUMP
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif /* HAVE_STDINT_H */
-static void debug_dump(const void *ptr,size_t size)
+static void debug_dump(const void *ptr, size_t size)
{
int i;
- for (i=0;i<size;i++)
- fprintf(stderr," %02x",((const uint8_t *)ptr)[i]);
- fprintf(stderr,"\n");
+ for (i = 0; i < size; i++)
+ fprintf(stderr, " %02x", ((const uint8_t *)ptr)[i]);
+ fprintf(stderr, "\n");
}
-#define DEBUG_DUMP(ptr,size) \
- fprintf(stderr,"%s:%d:%s:",__FILE__,__LINE__,__PRETTY_FUNCTION__); \
- debug_dump(ptr,size);
+#define DEBUG_DUMP(ptr, size) \
+ fprintf(stderr, "%s:%d:%s:", __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+ debug_dump(ptr, size);
#else /* DEBUG_PROT_DUMP */
/* define an empty debug macro to disable logging */
-#define DEBUG_DUMP(ptr,size)
+#define DEBUG_DUMP(ptr, size)
#endif /* not DEBUG_PROT_DUMP */
int32_t tmpint32; - temporary variable
*/
-#define WRITE(fp,ptr,size) \
- DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d",(int)size); \
- DEBUG_DUMP(ptr,size); \
- if (tio_write(fp,ptr,(size_t)size)) \
- { \
- DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s",strerror(errno)); \
- ERROR_OUT_WRITEERROR(fp); \
+#define WRITE(fp, ptr, size) \
+ DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d", (int)size); \
+ DEBUG_DUMP(ptr, size); \
+ if (tio_write(fp, ptr, (size_t)size)) \
+ { \
+ DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s", \
+ strerror(errno)); \
+ ERROR_OUT_WRITEERROR(fp); \
}
-#define WRITE_TYPE(fp,field,type) \
- WRITE(fp,&(field),sizeof(type))
-
-#define WRITE_INT32(fp,i) \
- DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%d",(int)i); \
- tmpint32=(int32_t)(i); \
- WRITE_TYPE(fp,tmpint32,int32_t)
-
-#define WRITE_STRING(fp,str) \
- DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"",(str)); \
- if ((str)==NULL) \
- { \
- WRITE_INT32(fp,0); \
- } \
- else \
- { \
- WRITE_INT32(fp,strlen(str)); \
- if (tmpint32>0) \
- { WRITE(fp,(str),tmpint32); } \
+#define WRITE_INT32(fp, i) \
+ DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%08x", (int)i); \
+ tmpint32 = htonl((int32_t)(i)); \
+ WRITE(fp, &tmpint32, sizeof(int32_t))
+
+#define WRITE_STRING(fp, str) \
+ DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"", (str)); \
+ if ((str) == NULL) \
+ { \
+ WRITE_INT32(fp, 0); \
+ } \
+ else \
+ { \
+ WRITE_INT32(fp, strlen(str)); \
+ tmpint32 = ntohl(tmpint32); \
+ if (tmpint32 > 0) \
+ { \
+ WRITE(fp, (str), tmpint32); \
+ } \
}
-#define WRITE_STRINGLIST(fp,arr) \
- if ((arr)==NULL) \
- { \
- DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",0); \
- WRITE_INT32(fp,0); \
- } \
- else \
- { \
- /* first determin length of array */ \
- for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
- /*noting*/ ; \
- /* write number of strings */ \
- DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
- WRITE_TYPE(fp,tmp3int32,int32_t); \
- /* write strings */ \
- for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
- { \
- WRITE_STRING(fp,(arr)[tmp2int32]); \
- } \
+#define WRITE_STRINGLIST(fp, arr) \
+ if ((arr) == NULL) \
+ { \
+ DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", 0); \
+ WRITE_INT32(fp, 0); \
+ } \
+ else \
+ { \
+ /* first determine length of array */ \
+ for (tmp3int32 = 0; (arr)[tmp3int32] != NULL; tmp3int32++) \
+ /* noting */ ; \
+ /* write number of strings */ \
+ DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
+ WRITE_INT32(fp, tmp3int32); \
+ /* write strings */ \
+ for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
+ { \
+ WRITE_STRING(fp, (arr)[tmp2int32]); \
+ } \
}
-#define WRITE_STRINGLIST_EXCEPT(fp,arr,not) \
- /* first determin length of array */ \
- tmp3int32=0; \
- for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
- if (strcmp((arr)[tmp2int32],(not))!=0) \
- tmp3int32++; \
- /* write number of strings (mius one because we intend to skip one) */ \
- DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
- WRITE_TYPE(fp,tmp3int32,int32_t); \
- /* write strings */ \
- for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
- { \
- if (strcmp((arr)[tmp2int32],(not))!=0) \
- { \
- WRITE_STRING(fp,(arr)[tmp2int32]); \
- } \
+#define WRITE_STRINGLIST_EXCEPT(fp, arr, not) \
+ /* first determine length of array */ \
+ tmp3int32 = 0; \
+ for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++) \
+ if (strcmp((arr)[tmp2int32], (not)) != 0) \
+ tmp3int32++; \
+ /* write number of strings (mius one because we intend to skip one) */ \
+ DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
+ WRITE_INT32(fp, tmp3int32); \
+ /* write strings */ \
+ for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++) \
+ { \
+ if (strcmp((arr)[tmp2int32], (not)) != 0) \
+ { \
+ WRITE_STRING(fp, (arr)[tmp2int32]); \
+ } \
}
-
/* READ macros, used for reading data, on read error they will
call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
these macros may require the availability of the following
int32_t tmpint32; - temporary variable
*/
-#define READ(fp,ptr,size) \
- if (tio_read(fp,ptr,(size_t)size)) \
- { \
- DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s",strerror(errno)); \
- ERROR_OUT_READERROR(fp); \
- } \
- DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d",(int)size); \
- DEBUG_DUMP(ptr,size);
-
-#define READ_TYPE(fp,field,type) \
- READ(fp,&(field),sizeof(type))
-
-#define READ_INT32(fp,i) \
- READ_TYPE(fp,tmpint32,int32_t); \
- i=tmpint32; \
- DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32=%d",(int)i);
+#define READ(fp, ptr, size) \
+ if (tio_read(fp, ptr, (size_t)size)) \
+ { \
+ DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s", \
+ strerror(errno)); \
+ ERROR_OUT_READERROR(fp); \
+ } \
+ DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d", (int)(size)); \
+ DEBUG_DUMP(ptr, size);
+
+#define READ_INT32(fp, i) \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ (i) = (int32_t)ntohl(tmpint32); \
+ DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32==%08x", (int)(i));
/* read a string in a fixed-size "normal" buffer */
-#define READ_STRING(fp,buffer) \
- /* read the size of the string */ \
- READ_TYPE(fp,tmpint32,int32_t); \
- DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d",tmpint32); \
- /* check if read would fit */ \
- if (((size_t)tmpint32)>=sizeof(buffer)) \
- { \
- /* will not fit */ \
- tmpint32=(tmpint32-sizeof(buffer))+1; \
- DEBUG_PRINT("READ : buffer %d bytes too small",tmpint32); \
- ERROR_OUT_BUFERROR(fp); \
- } \
- /* read string from the stream */ \
- if (tmpint32>0) \
- { READ(fp,buffer,(size_t)tmpint32); } \
- /* null-terminate string in buffer */ \
- buffer[tmpint32]='\0'; \
- DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"",buffer);
+#define READ_STRING(fp, buffer) \
+ /* read the size of the string */ \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d", tmpint32); \
+ /* check if read would fit */ \
+ if (((size_t)tmpint32) >= sizeof(buffer)) \
+ { \
+ /* will not fit */ \
+ tmpint32 = (tmpint32 - sizeof(buffer)) + 1; \
+ DEBUG_PRINT("READ : buffer %d bytes too small", tmpint32); \
+ ERROR_OUT_BUFERROR(fp); \
+ } \
+ /* read string from the stream */ \
+ if (tmpint32 > 0) \
+ { \
+ READ(fp, buffer, (size_t)tmpint32); \
+ } \
+ /* null-terminate string in buffer */ \
+ buffer[tmpint32] = '\0'; \
+ DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"", buffer);
/* READ BUF macros that read data into a pre-allocated buffer.
*/
/* current position in the buffer */
-#define BUF_CUR \
- (buffer+bufptr)
+#define BUF_CUR \
+ (buffer + bufptr)
/* check that the buffer has sz bytes left in it */
-#define BUF_CHECK(fp,sz) \
- if ((bufptr+(size_t)(sz))>buflen) \
- { \
- /* will not fit */ \
- tmpint32=bufptr+(sz)-(buflen); \
- DEBUG_PRINT("READ : buffer %d bytes too small",tmpint32); \
- ERROR_OUT_BUFERROR(fp); \
+#define BUF_CHECK(fp, sz) \
+ if ((bufptr + (size_t)(sz)) > buflen) \
+ { \
+ /* will not fit */ \
+ tmpint32 = bufptr + (sz) - (buflen); \
+ DEBUG_PRINT("READ : buffer %d bytes too small", tmpint32); \
+ ERROR_OUT_BUFERROR(fp); \
}
/* move the buffer pointer */
-#define BUF_SKIP(sz) \
- bufptr+=(size_t)(sz);
+#define BUF_SKIP(sz) \
+ bufptr += (size_t)(sz);
/* move BUF_CUR foreward so that it is aligned to the specified
type width */
-#define BUF_ALIGN(fp,type) \
- /* figure out number of bytes to skip foreward */ \
- tmp2int32=(sizeof(type)-((BUF_CUR-(char *)NULL)%sizeof(type)))%sizeof(type); \
- /* check and skip */ \
- BUF_CHECK(fp,tmp2int32); \
+#define BUF_ALIGN(fp, type) \
+ /* figure out number of bytes to skip foreward */ \
+ tmp2int32 = (sizeof(type) - ((BUF_CUR - (char *)NULL) % sizeof(type))) \
+ % sizeof(type); \
+ /* check and skip */ \
+ BUF_CHECK(fp, tmp2int32); \
BUF_SKIP(tmp2int32);
/* allocate a piece of the buffer to store an array in */
-#define BUF_ALLOC(fp,ptr,type,num) \
- /* align to the specified type width */ \
- BUF_ALIGN(fp,type); \
- /* check that we have enough room */ \
- BUF_CHECK(fp,(size_t)(num)*sizeof(type)); \
- /* store the pointer */ \
- (ptr)=(type *)BUF_CUR; \
- /* reserve the space */ \
- BUF_SKIP((size_t)(num)*sizeof(type));
+#define BUF_ALLOC(fp, ptr, type, num) \
+ /* align to the specified type width */ \
+ BUF_ALIGN(fp, type); \
+ /* check that we have enough room */ \
+ BUF_CHECK(fp, (size_t)(num) * sizeof(type)); \
+ /* store the pointer */ \
+ (ptr) = (type *)BUF_CUR; \
+ /* reserve the space */ \
+ BUF_SKIP((size_t)(num) * sizeof(type));
/* read a binary blob into the buffer */
-#define READ_BUF(fp,ptr,sz) \
- /* check that there is enough room and read */ \
- BUF_CHECK(fp,sz); \
- READ(fp,BUF_CUR,(size_t)sz); \
- /* store pointer and skip */ \
- (ptr)=BUF_CUR; \
+#define READ_BUF(fp, ptr, sz) \
+ /* check that there is enough room and read */ \
+ BUF_CHECK(fp, sz); \
+ READ(fp, BUF_CUR, (size_t)sz); \
+ /* store pointer and skip */ \
+ (ptr) = BUF_CUR; \
BUF_SKIP(sz);
/* read string in the buffer (using buffer, buflen and bufptr)
and store the actual location of the string in field */
-#define READ_BUF_STRING(fp,field) \
- /* read the size of the string */ \
- READ_TYPE(fp,tmpint32,int32_t); \
- DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d",tmpint32); \
- /* check if read would fit */ \
- BUF_CHECK(fp,tmpint32+1); \
- /* read string from the stream */ \
- if (tmpint32>0) \
- { READ(fp,BUF_CUR,(size_t)tmpint32); } \
- /* null-terminate string in buffer */ \
- BUF_CUR[tmpint32]='\0'; \
- DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"",BUF_CUR); \
- /* prepare result */ \
- (field)=BUF_CUR; \
- BUF_SKIP(tmpint32+1);
+#define READ_BUF_STRING(fp, field) \
+ /* read the size of the string */ \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d", tmpint32); \
+ /* check if read would fit */ \
+ BUF_CHECK(fp, tmpint32 + 1); \
+ /* read string from the stream */ \
+ if (tmpint32 > 0) \
+ { \
+ READ(fp, BUF_CUR, (size_t)tmpint32); \
+ } \
+ /* null-terminate string in buffer */ \
+ BUF_CUR[tmpint32] = '\0'; \
+ DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"", BUF_CUR); \
+ /* prepare result */ \
+ (field) = BUF_CUR; \
+ BUF_SKIP(tmpint32 + 1);
/* read an array from a stram and store it as a null-terminated
array list (size for the array is allocated) */
-#define READ_BUF_STRINGLIST(fp,arr) \
- /* read the number of entries */ \
- READ_TYPE(fp,tmp3int32,int32_t); \
- DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
- /* allocate room for *char[num+1] */ \
- BUF_ALLOC(fp,arr,char *,tmp3int32+1); \
- /* read all entries */ \
- for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
- { \
- READ_BUF_STRING(fp,(arr)[tmp2int32]); \
- } \
- /* set last entry to NULL */ \
- (arr)[tmp2int32]=NULL;
+#define READ_BUF_STRINGLIST(fp, arr) \
+ /* read the number of entries */ \
+ READ(fp, &tmp3int32, sizeof(int32_t)); \
+ tmp3int32 = ntohl(tmp3int32); \
+ DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
+ /* allocate room for *char[num + 1] */ \
+ BUF_ALLOC(fp, arr, char *, tmp3int32 + 1); \
+ /* read all entries */ \
+ for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
+ { \
+ READ_BUF_STRING(fp, (arr)[tmp2int32]); \
+ } \
+ /* set last entry to NULL */ \
+ (arr)[tmp2int32] = NULL;
/* SKIP macros for skipping over certain parts of the protocol stream. */
/* skip a number of bytes foreward */
-#define SKIP(fp,sz) \
- DEBUG_PRINT("READ : skip %d bytes",(int)(sz)); \
- /* read (skip) the specified number of bytes */ \
- if (tio_skip(fp,sz)) \
- { \
- DEBUG_PRINT("READ : skip error: %s",strerror(errno)); \
- ERROR_OUT_READERROR(fp); \
+#define SKIP(fp, sz) \
+ DEBUG_PRINT("READ : skip %d bytes", (int)(sz)); \
+ /* read (skip) the specified number of bytes */ \
+ if (tio_skip(fp, sz)) \
+ { \
+ DEBUG_PRINT("READ : skip error: %s", strerror(errno)); \
+ ERROR_OUT_READERROR(fp); \
}
/* read a string from the stream but don't do anything with the result */
-#define SKIP_STRING(fp) \
- /* read the size of the string */ \
- READ_TYPE(fp,tmpint32,int32_t); \
- DEBUG_PRINT("READ_STRING: skip %d bytes",(int)tmpint32); \
- /* read (skip) the specified number of bytes */ \
- SKIP(fp,tmpint32);
+#define SKIP_STRING(fp) \
+ /* read the size of the string */ \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ DEBUG_PRINT("READ_STRING: skip %d bytes", (int)tmpint32); \
+ /* read (skip) the specified number of bytes */ \
+ SKIP(fp, tmpint32);
/* skip a list of strings */
-#define SKIP_STRINGLIST(fp) \
- /* read the number of entries */ \
- READ_TYPE(fp,tmp3int32,int32_t); \
- DEBUG_PRINT("READ_STRLST: skip %d strings",(int)tmp3int32); \
- /* read all entries */ \
- for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
- { \
- SKIP_STRING(fp); \
+#define SKIP_STRINGLIST(fp) \
+ /* read the number of entries */ \
+ READ(fp, &tmp3int32, sizeof(int32_t)); \
+ tmp3int32 = ntohl(tmp3int32); \
+ DEBUG_PRINT("READ_STRLST: skip %d strings", (int)tmp3int32); \
+ /* read all entries */ \
+ for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
+ { \
+ SKIP_STRING(fp); \
}
MUST_USE;
/* generic request code */
-#define NSLCD_REQUEST(fp,action,writefn) \
- /* open a client socket */ \
- if ((fp=nslcd_client_open())==NULL) \
- { ERROR_OUT_OPENERROR } \
- /* write a request header with a request code */ \
- WRITE_INT32(fp,(int32_t)NSLCD_VERSION) \
- WRITE_INT32(fp,(int32_t)action) \
- /* write the request parameters (if any) */ \
- writefn; \
- /* flush the stream */ \
- if (tio_flush(fp)<0) \
- { \
- DEBUG_PRINT("WRITE_FLUSH : error: %s",strerror(errno)); \
- ERROR_OUT_WRITEERROR(fp); \
- } \
- /* read and check response version number */ \
- READ_TYPE(fp,tmpint32,int32_t); \
- if (tmpint32!=(int32_t)NSLCD_VERSION) \
- { ERROR_OUT_READERROR(fp) } \
- /* read and check response request number */ \
- READ_TYPE(fp,tmpint32,int32_t); \
- if (tmpint32!=(int32_t)(action)) \
- { ERROR_OUT_READERROR(fp) }
+#define NSLCD_REQUEST(fp, action, writefn) \
+ /* open a client socket */ \
+ if ((fp = nslcd_client_open()) == NULL) \
+ { \
+ ERROR_OUT_OPENERROR; \
+ } \
+ /* write a request header with a request code */ \
+ WRITE_INT32(fp, (int32_t)NSLCD_VERSION) \
+ WRITE_INT32(fp, (int32_t)action) \
+ /* write the request parameters (if any) */ \
+ writefn; \
+ /* flush the stream */ \
+ if (tio_flush(fp) < 0) \
+ { \
+ DEBUG_PRINT("WRITE_FLUSH : error: %s", strerror(errno)); \
+ ERROR_OUT_WRITEERROR(fp); \
+ } \
+ /* read and check response version number */ \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ if (tmpint32 != (int32_t)NSLCD_VERSION) \
+ { \
+ ERROR_OUT_READERROR(fp); \
+ } \
+ /* read and check response request number */ \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ if (tmpint32 != (int32_t)(action)) \
+ { \
+ ERROR_OUT_READERROR(fp); \
+ }
/* Read the response code (the result code of the query) from
the stream. */
-#define READ_RESPONSE_CODE(fp) \
- READ_TYPE(fp,tmpint32,int32_t); \
- if (tmpint32!=(int32_t)NSLCD_RESULT_BEGIN) \
- { ERROR_OUT_NOSUCCESS(fp) }
+#define READ_RESPONSE_CODE(fp) \
+ READ(fp, &tmpint32, sizeof(int32_t)); \
+ tmpint32 = ntohl(tmpint32); \
+ if (tmpint32 != (int32_t)NSLCD_RESULT_BEGIN) \
+ { \
+ ERROR_OUT_NOSUCCESS(fp); \
+ }
#endif /* not COMMON__NSLCD_PROT_H */
nslcd.h - file describing client/server protocol
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012 Arthur de Jong
+ Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012, 2013 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Furthermore the ADDRESS compound data type is defined as:
INT32 type of address: e.g. AF_INET or AF_INET6
INT32 lenght of address
- RAW the address itself in network byte order
+ RAW the address itself
With the ADDRESSLIST using the same construct as with STRINGLIST.
- The protocol uses host-byte order for all types (except in the raw
- address above).
+ The protocol uses network byte order for all types.
*/
-/* The current version of the protocol. Note that version 1
- is experimental and this version will be used until a
- 1.0 release of nss-pam-ldapd is made. */
-#define NSLCD_VERSION 1
+/* The current version of the protocol. This protocol should only be
+ updated with major backwards-incompatible changes. */
+#define NSLCD_VERSION 0x00000002
/* Get a NSLCD configuration option. There is one request parameter:
INT32 NSLCD_CONFIG_*
the result value is:
STRING value, interpretation depending on request */
-#define NSLCD_ACTION_CONFIG_GET 20006
+#define NSLCD_ACTION_CONFIG_GET 0x00010001
/* return the message, if any, that is presented to the user when password
modification through PAM is prohibited */
-#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 852
+#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 1
/* Email alias (/etc/aliases) NSS requests. The result values for a
single entry are:
STRING alias name
STRINGLIST alias rcpts */
-#define NSLCD_ACTION_ALIAS_BYNAME 4001
-#define NSLCD_ACTION_ALIAS_ALL 4002
+#define NSLCD_ACTION_ALIAS_BYNAME 0x00020001
+#define NSLCD_ACTION_ALIAS_ALL 0x00020008
/* Ethernet address/name mapping NSS requests. The result values for a
single entry are:
STRING ether name
TYPE(uint8_t[6]) ether address */
-#define NSLCD_ACTION_ETHER_BYNAME 3001
-#define NSLCD_ACTION_ETHER_BYETHER 3002
-#define NSLCD_ACTION_ETHER_ALL 3005
+#define NSLCD_ACTION_ETHER_BYNAME 0x00030001
+#define NSLCD_ACTION_ETHER_BYETHER 0x00030002
+#define NSLCD_ACTION_ETHER_ALL 0x00030008
/* Group and group membership related NSS requests. The result values
for a single entry are:
STRING group name
STRING group password
- TYPE(gid_t) group id
+ INT32 group id
STRINGLIST members (usernames) of the group
(not that the BYMEMER call returns an emtpy members list) */
-#define NSLCD_ACTION_GROUP_BYNAME 5001
-#define NSLCD_ACTION_GROUP_BYGID 5002
-#define NSLCD_ACTION_GROUP_BYMEMBER 5003
-#define NSLCD_ACTION_GROUP_ALL 5004
+#define NSLCD_ACTION_GROUP_BYNAME 0x00040001
+#define NSLCD_ACTION_GROUP_BYGID 0x00040002
+#define NSLCD_ACTION_GROUP_BYMEMBER 0x00040006
+#define NSLCD_ACTION_GROUP_ALL 0x00040008
/* Hostname (/etc/hosts) lookup NSS requests. The result values
for an entry are:
STRING host name
STRINGLIST host aliases
ADDRESSLIST host addresses */
-#define NSLCD_ACTION_HOST_BYNAME 6001
-#define NSLCD_ACTION_HOST_BYADDR 6002
-#define NSLCD_ACTION_HOST_ALL 6005
-
-/* Netgroup NSS request return a number of results. Result values
- can be either a reference to another netgroup:
+#define NSLCD_ACTION_HOST_BYNAME 0x00050001
+#define NSLCD_ACTION_HOST_BYADDR 0x00050002
+#define NSLCD_ACTION_HOST_ALL 0x00050008
+
+/* Netgroup NSS result entries contain a number of parts. A result entry
+ starts with:
+ STRING netgroup name
+ followed by zero or more references to other netgroups or netgroup
+ triples. A reference to another netgroup looks like:
INT32 NSLCD_NETGROUP_TYPE_NETGROUP
STRING other netgroup name
- or a netgroup triple:
+ A a netgroup triple looks like:
INT32 NSLCD_NETGROUP_TYPE_TRIPLE
STRING host
STRING user
- STRING domain */
-#define NSLCD_ACTION_NETGROUP_BYNAME 12001
-#define NSLCD_NETGROUP_TYPE_NETGROUP 123
-#define NSLCD_NETGROUP_TYPE_TRIPLE 456
+ STRING domain
+ A netgroup result entry is terminated by:
+ INT32 NSLCD_NETGROUP_TYPE_END
+ */
+#define NSLCD_ACTION_NETGROUP_BYNAME 0x00060001
+#define NSLCD_ACTION_NETGROUP_ALL 0x00060008
+#define NSLCD_NETGROUP_TYPE_NETGROUP 1
+#define NSLCD_NETGROUP_TYPE_TRIPLE 2
+#define NSLCD_NETGROUP_TYPE_END 3
/* Network name (/etc/networks) NSS requests. Result values for a single
entry are:
STRING network name
STRINGLIST network aliases
ADDRESSLIST network addresses */
-#define NSLCD_ACTION_NETWORK_BYNAME 8001
-#define NSLCD_ACTION_NETWORK_BYADDR 8002
-#define NSLCD_ACTION_NETWORK_ALL 8005
+#define NSLCD_ACTION_NETWORK_BYNAME 0x00070001
+#define NSLCD_ACTION_NETWORK_BYADDR 0x00070002
+#define NSLCD_ACTION_NETWORK_ALL 0x00070008
/* User account (/etc/passwd) NSS requests. Result values are:
STRING user name
STRING user password
- TYPE(uid_t) user id
- TYPE(gid_t) group id
+ INT32 user id
+ INT32 group id
STRING gecos information
STRING home directory
STRING login shell */
-#define NSLCD_ACTION_PASSWD_BYNAME 1001
-#define NSLCD_ACTION_PASSWD_BYUID 1002
-#define NSLCD_ACTION_PASSWD_ALL 1004
+#define NSLCD_ACTION_PASSWD_BYNAME 0x00080001
+#define NSLCD_ACTION_PASSWD_BYUID 0x00080002
+#define NSLCD_ACTION_PASSWD_ALL 0x00080008
/* Protocol information requests. Result values are:
STRING protocol name
STRINGLIST protocol aliases
INT32 protocol number */
-#define NSLCD_ACTION_PROTOCOL_BYNAME 9001
-#define NSLCD_ACTION_PROTOCOL_BYNUMBER 9002
-#define NSLCD_ACTION_PROTOCOL_ALL 9003
+#define NSLCD_ACTION_PROTOCOL_BYNAME 0x00090001
+#define NSLCD_ACTION_PROTOCOL_BYNUMBER 0x00090002
+#define NSLCD_ACTION_PROTOCOL_ALL 0x00090008
/* RPC information requests. Result values are:
STRING rpc name
STRINGLIST rpc aliases
INT32 rpc number */
-#define NSLCD_ACTION_RPC_BYNAME 10001
-#define NSLCD_ACTION_RPC_BYNUMBER 10002
-#define NSLCD_ACTION_RPC_ALL 10003
+#define NSLCD_ACTION_RPC_BYNAME 0x000a0001
+#define NSLCD_ACTION_RPC_BYNUMBER 0x000a0002
+#define NSLCD_ACTION_RPC_ALL 0x000a0008
-/* Service (/etc/services) information requests. Result values are:
+/* Service (/etc/services) information requests. The BYNAME and BYNUMBER
+ requests contain an extra protocol string in the request which, if not
+ blank, will filter the services by this protocol. Result values are:
STRING service name
STRINGLIST service aliases
INT32 service (port) number
STRING service protocol */
-#define NSLCD_ACTION_SERVICE_BYNAME 11001
-#define NSLCD_ACTION_SERVICE_BYNUMBER 11002
-#define NSLCD_ACTION_SERVICE_ALL 11005
+#define NSLCD_ACTION_SERVICE_BYNAME 0x000b0001
+#define NSLCD_ACTION_SERVICE_BYNUMBER 0x000b0002
+#define NSLCD_ACTION_SERVICE_ALL 0x000b0008
/* Extended user account (/etc/shadow) information requests. Result
values for a single entry are:
INT32 inact
INT32 expire
INT32 flag */
-#define NSLCD_ACTION_SHADOW_BYNAME 2001
-#define NSLCD_ACTION_SHADOW_ALL 2005
+#define NSLCD_ACTION_SHADOW_BYNAME 0x000c0001
+#define NSLCD_ACTION_SHADOW_ALL 0x000c0008
/* PAM-related requests. The request parameters for all these requests
begin with:
STRING user name
- STRING DN (if value is known already, otherwise empty)
STRING service name
- all requests, except the SESSION requests start the result value with:
- STRING user name (cannonical name)
- STRING DN (can be used to speed up requests)
- Some functions may return an authorisation message. This message, if
- supplied will be used by the PAM module instead of a message that is
- generated by the PAM module itself. */
+ STRING ruser
+ STRING rhost
+ STRING tty
+ If the user is not known in LDAP no result may be returned (immediately
+ return NSLCD_RESULT_END instead of a PAM error code). */
/* PAM authentication check request. The extra request values are:
STRING password
- and the result value ends with:
+ and the result value consists of:
INT32 authc NSLCD_PAM_* result code
+ STRING user name (the cannonical user name)
INT32 authz NSLCD_PAM_* result code
STRING authorisation error message
If the username is empty in this request an attempt is made to
- authenticate as the administrator (set using rootpwmoddn). The returned DN
- is that of the administrator. */
-#define NSLCD_ACTION_PAM_AUTHC 20001
-
-/* PAM authorisation check request. The extra request values are:
- STRING ruser
- STRING rhost
- STRING tty
- and the result value ends with:
+ authenticate as the administrator (set using rootpwmoddn).
+ Some authorisation checks are already done during authentication so the
+ response also includes authorisation information. */
+#define NSLCD_ACTION_PAM_AUTHC 0x000d0001
+
+/* PAM authorisation check request. The result value consists of:
INT32 authz NSLCD_PAM_* result code
- STRING authorisation error message */
-#define NSLCD_ACTION_PAM_AUTHZ 20002
-
-/* PAM session open and close requests. These requests have the following
- extra request values:
- STRING tty
- STRING rhost
- STRING ruser
- INT32 session id (ignored for SESS_O)
- and these calls only return the session ID:
- INT32 session id
- The SESS_C must contain the ID that is retured by SESS_O to close the
- correct session. */
-#define NSLCD_ACTION_PAM_SESS_O 20003
-#define NSLCD_ACTION_PAM_SESS_C 20004
+ STRING authorisation error message
+ The authentication check may have already returned some authorisation
+ information. The authorisation error message, if supplied, will be used
+ by the PAM module instead of a message that is generated by the PAM
+ module itself. */
+#define NSLCD_ACTION_PAM_AUTHZ 0x000d0002
+
+/* PAM session open request. The result value consists of:
+ STRING session id
+ This session id may be used to close this session with. */
+#define NSLCD_ACTION_PAM_SESS_O 0x000d0003
+
+/* PAM session close request. This request has the following
+ extra request value:
+ STRING session id
+ and this calls only returns an empty response value. */
+#define NSLCD_ACTION_PAM_SESS_C 0x000d0004
/* PAM password modification request. This requests has the following extra
request values:
- STRING old password
- STRING new password
+ INT32 asroot: 0=oldpasswd is user passwd, 1=oldpasswd is root passwd
+ STRING old password
+ STRING new password
and returns there extra result values:
- INT32 authz NSLCD_PAM_* result code
- STRING authorisation error message
- In this request the DN may be set to the administrator's DN. In this
- case old password should be the administrator's password. This allows
- the administrator to change any user's password. */
-#define NSLCD_ACTION_PAM_PWMOD 20005
+ INT32 NSLCD_PAM_* result code
+ STRING error message */
+#define NSLCD_ACTION_PAM_PWMOD 0x000d0005
+
+/* User information change request. This request allows one to change
+ their full name and other information. The request parameters for this
+ request are:
+ STRING user name
+ INT32 asroot: 0=passwd is user passwd, 1=passwd is root passwd
+ STRING password
+ followed by one or more of the below, terminated by NSLCD_USERMOD_END
+ INT32 NSLCD_USERMOD_*
+ STRING new value
+ the response consists of one or more of the entries below, terminated
+ by NSLCD_USERMOD_END:
+ INT32 NSLCD_USERMOD_*
+ STRING response
+ (if the response is blank, the change went OK, otherwise the string
+ contains an error message)
+ */
+#define NSLCD_ACTION_USERMOD 0x000e0001
+
+/* These are the possible values for the NSLCD_ACTION_USERMOD operation
+ above. */
+#define NSLCD_USERMOD_END 0 /* end of change values */
+#define NSLCD_USERMOD_RESULT 1 /* global result value */
+#define NSLCD_USERMOD_FULLNAME 2 /* full name */
+#define NSLCD_USERMOD_ROOMNUMBER 3 /* room number */
+#define NSLCD_USERMOD_WORKPHONE 4 /* office phone number */
+#define NSLCD_USERMOD_HOMEPHONE 5 /* home phone number */
+#define NSLCD_USERMOD_OTHER 6 /* other info */
+#define NSLCD_USERMOD_HOMEDIR 7 /* home directory */
+#define NSLCD_USERMOD_SHELL 8 /* login shell */
/* Request result codes. */
-#define NSLCD_RESULT_BEGIN 0
-#define NSLCD_RESULT_END 3
+#define NSLCD_RESULT_BEGIN 1
+#define NSLCD_RESULT_END 2
/* Partial list of PAM result codes. */
#define NSLCD_PAM_SUCCESS 0 /* everything ok */
tio.c - timed io functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008, 2010, 2011, 2012 Arthur de Jong
+ Copyright (C) 2007-2014 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
02110-1301 USA
*/
-//#include "config.h"
#include "portable.h"
#ifdef HAVE_STDINT_H
#include <stdio.h>
#include <limits.h>
#include <poll.h>
+#include <time.h>
#include "tio.h"
#endif /* DEBUG_TIO_STATS */
};
-/* build a timeval for comparison to when the operation should be finished */
-static inline void tio_get_deadline(struct timeval *deadline,int timeout)
-{
- if (gettimeofday(deadline,NULL))
- {
- /* just blank it in case of errors */
- deadline->tv_sec=0;
- deadline->tv_usec=0;
- return;
- }
- deadline->tv_sec+=timeout/1000;
- deadline->tv_sec+=(timeout%1000)*1000;
-}
+/* some older versions of Solaris don't provide CLOCK_MONOTONIC but do have
+ a CLOCK_HIGHRES that has the same properties we need */
+#ifndef CLOCK_MONOTONIC
+#ifdef CLOCK_HIGHRES
+#define CLOCK_MONOTONIC CLOCK_HIGHRES
+#endif /* CLOCK_HIGHRES */
+#endif /* not CLOCK_MONOTONIC */
-/* update the timeout to the value that is remaining before deadline
- returns non-zero if there is no more time before the deadline */
-static inline int tio_time_remaining(const struct timeval *deadline)
+/* update the timeout to the value that is remaining before the deadline
+ returns the number of milliseconds before the deadline (or a negative
+ value of the deadline has expired) */
+static inline int tio_time_remaining(struct timespec *deadline, int timeout)
{
- struct timeval tv;
- /* get the current time */
- if (gettimeofday(&tv,NULL))
+ struct timespec tv;
+ /* if this is the first call, set the deadline and return the full time */
+ if ((deadline->tv_sec == 0) && (deadline->tv_nsec == 0))
{
- /* 1 second default if gettimeofday() is broken */
- return 1000;
+ if (clock_gettime(CLOCK_MONOTONIC, deadline) == 0)
+ {
+ deadline->tv_sec += timeout / 1000;
+ deadline->tv_nsec += (timeout % 1000) * 1000000;
+ }
+ return timeout;
}
- /* calculate time remaining in miliseconds */
- return (deadline->tv_sec-tv.tv_sec)*1000 + (deadline->tv_usec-tv.tv_usec)/1000;
+ /* get the current time (fall back to full time on error) */
+ if (clock_gettime(CLOCK_MONOTONIC, &tv))
+ return timeout;
+ /* calculate time remaining in milliseconds */
+ return (deadline->tv_sec - tv.tv_sec) * 1000 +
+ (deadline->tv_nsec - tv.tv_nsec) / 1000000;
}
/* open a new TFILE based on the file descriptor */
-TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
- size_t initreadsize,size_t maxreadsize,
- size_t initwritesize,size_t maxwritesize)
+TFILE *tio_fdopen(int fd, int readtimeout, int writetimeout,
+ size_t initreadsize, size_t maxreadsize,
+ size_t initwritesize, size_t maxwritesize)
{
struct tio_fileinfo *fp;
- fp=(struct tio_fileinfo *)malloc(sizeof(struct tio_fileinfo));
- if (fp==NULL)
+ fp = (struct tio_fileinfo *)malloc(sizeof(struct tio_fileinfo));
+ if (fp == NULL)
return NULL;
- fp->fd=fd;
+ fp->fd = fd;
/* initialize read buffer */
- fp->readbuffer.buffer=(uint8_t *)malloc(initreadsize);
- if (fp->readbuffer.buffer==NULL)
+ fp->readbuffer.buffer = (uint8_t *)malloc(initreadsize);
+ if (fp->readbuffer.buffer == NULL)
{
free(fp);
return NULL;
}
- fp->readbuffer.size=initreadsize;
- fp->readbuffer.maxsize=maxreadsize;
- fp->readbuffer.start=0;
- fp->readbuffer.len=0;
+ fp->readbuffer.size = initreadsize;
+ fp->readbuffer.maxsize = maxreadsize;
+ fp->readbuffer.start = 0;
+ fp->readbuffer.len = 0;
/* initialize write buffer */
- fp->writebuffer.buffer=(uint8_t *)malloc(initwritesize);
- if (fp->writebuffer.buffer==NULL)
+ fp->writebuffer.buffer = (uint8_t *)malloc(initwritesize);
+ if (fp->writebuffer.buffer == NULL)
{
free(fp->readbuffer.buffer);
free(fp);
return NULL;
}
- fp->writebuffer.size=initwritesize;
- fp->writebuffer.maxsize=maxwritesize;
- fp->writebuffer.start=0;
- fp->writebuffer.len=0;
+ fp->writebuffer.size = initwritesize;
+ fp->writebuffer.maxsize = maxwritesize;
+ fp->writebuffer.start = 0;
+ fp->writebuffer.len = 0;
/* initialize other attributes */
- fp->readtimeout=readtimeout;
- fp->writetimeout=writetimeout;
- fp->read_resettable=0;
+ fp->readtimeout = readtimeout;
+ fp->writetimeout = writetimeout;
+ fp->read_resettable = 0;
#ifdef DEBUG_TIO_STATS
- fp->byteswritten=0;
- fp->bytesread=0;
+ fp->byteswritten = 0;
+ fp->bytesread = 0;
#endif /* DEBUG_TIO_STATS */
return fp;
}
/* wait for any activity on the specified file descriptor using
the specified deadline */
-static int tio_wait(TFILE *fp,int readfd,const struct timeval *deadline)
+static int tio_wait(int fd, short events, int timeout,
+ struct timespec *deadline)
{
- int timeout;
+ int t;
struct pollfd fds[1];
int rv;
while (1)
{
+ fds[0].fd = fd;
+ fds[0].events = events;
/* figure out the time we need to wait */
- if ((timeout=tio_time_remaining(deadline))<0)
+ if ((t = tio_time_remaining(deadline, timeout)) < 0)
{
- errno=ETIME;
+ errno = ETIME;
return -1;
}
+ /* sanitiy check for moving clock */
+ if (t > timeout)
+ t = timeout;
/* wait for activity */
- if (readfd)
- {
- fds[0].fd=fp->fd;
- fds[0].events=POLLIN;
- /* santiy check for moving clock */
- if (timeout>fp->readtimeout)
- timeout=fp->readtimeout;
- }
- else
- {
- fds[0].fd=fp->fd;
- fds[0].events=POLLOUT;
- /* santiy check for moving clock */
- if (timeout>fp->writetimeout)
- timeout=fp->writetimeout;
- }
- rv=poll(fds,1,timeout);
- if (rv>0)
+ rv = poll(fds, 1, t);
+ if (rv > 0)
return 0; /* we have activity */
- else if (rv==0)
+ else if (rv == 0)
{
/* no file descriptors were available within the specified time */
- errno=ETIME;
+ errno = ETIME;
return -1;
}
- else if (errno!=EINTR)
+ else if ((errno != EINTR) && (errno != EAGAIN))
/* some error ocurred */
return -1;
- /* we just try again on EINTR */
+ /* we just try again on EINTR or EAGAIN */
}
}
if no data was read in the specified time an error is returned */
int tio_read(TFILE *fp, void *buf, size_t count)
{
- struct timeval deadline;
+ struct timespec deadline = {0, 0};
int rv;
uint8_t *tmp;
size_t newsz;
size_t len;
/* have a more convenient storage type for the buffer */
- uint8_t *ptr=(uint8_t *)buf;
- /* build a time by which we should be finished */
- tio_get_deadline(&deadline,fp->readtimeout);
+ uint8_t *ptr = (uint8_t *)buf;
/* loop until we have returned all the needed data */
while (1)
{
/* check if we have enough data in the buffer */
if (fp->readbuffer.len >= count)
{
- if (count>0)
+ if (count > 0)
{
- if (ptr!=NULL)
- memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,count);
+ if (ptr != NULL)
+ memcpy(ptr, fp->readbuffer.buffer + fp->readbuffer.start, count);
/* adjust buffer position */
- fp->readbuffer.start+=count;
- fp->readbuffer.len-=count;
+ fp->readbuffer.start += count;
+ fp->readbuffer.len -= count;
}
return 0;
}
/* empty what we have and continue from there */
- if (fp->readbuffer.len>0)
+ if (fp->readbuffer.len > 0)
{
- if (ptr!=NULL)
+ if (ptr != NULL)
{
- memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
- ptr+=fp->readbuffer.len;
+ memcpy(ptr, fp->readbuffer.buffer + fp->readbuffer.start,
+ fp->readbuffer.len);
+ ptr += fp->readbuffer.len;
}
- count-=fp->readbuffer.len;
- fp->readbuffer.start+=fp->readbuffer.len;
- fp->readbuffer.len=0;
+ count -= fp->readbuffer.len;
+ fp->readbuffer.start += fp->readbuffer.len;
+ fp->readbuffer.len = 0;
}
/* after this point until the read fp->readbuffer.len is 0 */
if (!fp->read_resettable)
{
/* the stream is not resettable, re-use the buffer */
- fp->readbuffer.start=0;
+ fp->readbuffer.start = 0;
}
- else if (fp->readbuffer.start>=(fp->readbuffer.size-4))
+ else if (fp->readbuffer.start >= (fp->readbuffer.size - 4))
{
/* buffer is running empty, try to grow buffer */
- if (fp->readbuffer.size<fp->readbuffer.maxsize)
+ if (fp->readbuffer.size < fp->readbuffer.maxsize)
{
- newsz=fp->readbuffer.size*2;
- if (newsz>fp->readbuffer.maxsize)
- newsz=fp->readbuffer.maxsize;
- tmp=realloc(fp->readbuffer.buffer,newsz);
- if (tmp!=NULL)
+ newsz = fp->readbuffer.size * 2;
+ if (newsz > fp->readbuffer.maxsize)
+ newsz = fp->readbuffer.maxsize;
+ tmp = realloc(fp->readbuffer.buffer, newsz);
+ if (tmp != NULL)
{
- fp->readbuffer.buffer=tmp;
- fp->readbuffer.size=newsz;
+ fp->readbuffer.buffer = tmp;
+ fp->readbuffer.size = newsz;
}
}
/* if buffer still does not contain enough room, clear resettable */
- if (fp->readbuffer.start>=(fp->readbuffer.size-4))
+ if (fp->readbuffer.start >= (fp->readbuffer.size - 4))
{
- fp->readbuffer.start=0;
- fp->read_resettable=0;
+ fp->readbuffer.start = 0;
+ fp->read_resettable = 0;
}
}
/* wait until we have input */
- if (tio_wait(fp,1,&deadline))
+ if (tio_wait(fp->fd, POLLIN, fp->readtimeout, &deadline))
return -1;
/* read the input in the buffer */
- len=fp->readbuffer.size-fp->readbuffer.start;
+ len = fp->readbuffer.size - fp->readbuffer.start;
#ifdef SSIZE_MAX
- if (len>SSIZE_MAX)
- len=SSIZE_MAX;
+ if (len > SSIZE_MAX)
+ len = SSIZE_MAX;
#endif /* SSIZE_MAX */
- rv=read(fp->fd,fp->readbuffer.buffer+fp->readbuffer.start,len);
+ rv = read(fp->fd, fp->readbuffer.buffer + fp->readbuffer.start, len);
/* check for errors */
- if (rv==0)
+ if (rv == 0)
{
- errno=ECONNRESET;
+ errno = ECONNRESET;
return -1;
}
- else if ((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN))
- return -1; /* something went wrong with the read */
- /* skip the read part in the buffer */
- fp->readbuffer.len=rv;
+ else if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN))
+ return -1; /* something went wrong with the read */
+ else if (rv > 0)
+ fp->readbuffer.len = rv; /* skip the read part in the buffer */
#ifdef DEBUG_TIO_STATS
- fp->bytesread+=rv;
+ fp->bytesread += rv;
#endif /* DEBUG_TIO_STATS */
}
}
/* Read and discard the specified number of bytes from the stream. */
int tio_skip(TFILE *fp, size_t count)
{
- return tio_read(fp,NULL,count);
+ return tio_read(fp, NULL, count);
}
/* Read all available data from the stream and empty the read buffer. */
-int tio_skipall(TFILE *fp)
+int tio_skipall(TFILE *fp, int timeout)
{
- struct pollfd fds[1];
+ struct timespec deadline = {0, 0};
int rv;
size_t len;
/* clear the read buffer */
- fp->readbuffer.start=0;
- fp->readbuffer.len=0;
- fp->read_resettable=0;
+ fp->readbuffer.start = 0;
+ fp->readbuffer.len = 0;
+ fp->read_resettable = 0;
/* read until we can't read no more */
- len=fp->readbuffer.size;
+ len = fp->readbuffer.size;
#ifdef SSIZE_MAX
- if (len>SSIZE_MAX)
- len=SSIZE_MAX;
+ if (len > SSIZE_MAX)
+ len = SSIZE_MAX;
#endif /* SSIZE_MAX */
while (1)
{
- /* see if any data is available */
- fds[0].fd=fp->fd;
- fds[0].events=POLLIN;
- rv=poll(fds,1,0);
- /* check the poll() result */
- if (rv==0)
- return 0; /* no file descriptor ready */
- if ((rv<0)&&((errno==EINTR)||(errno==EAGAIN)))
- continue; /* interrupted, try again */
- if (rv<0)
- return -1; /* something went wrong */
+ /* wait until we have input */
+ if (tio_wait(fp->fd, POLLIN, timeout, &deadline))
+ return -1;
/* read data from the stream */
- rv=read(fp->fd,fp->readbuffer.buffer,len);
- if (rv==0)
+ rv = read(fp->fd, fp->readbuffer.buffer, len);
+ if (rv == 0)
return 0; /* end-of-file */
- if ((rv<0)&&(errno==EWOULDBLOCK))
+ if ((rv < 0) && (errno == EWOULDBLOCK))
return 0; /* we've ready everything we can without blocking */
- if ((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN))
+ if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN))
return -1; /* something went wrong with the read */
}
}
int rv;
/* write the buffer */
#ifdef MSG_NOSIGNAL
- rv=send(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len,MSG_NOSIGNAL);
+ rv = send(fp->fd, fp->writebuffer.buffer + fp->writebuffer.start,
+ fp->writebuffer.len, MSG_NOSIGNAL);
#else /* not MSG_NOSIGNAL */
/* on platforms that cannot use send() with masked signals, we change the
signal mask and change it back after the write (note that there is a
race condition here) */
- struct sigaction act,oldact;
+ struct sigaction act, oldact;
/* set up sigaction */
- memset(&act,0,sizeof(struct sigaction));
- act.sa_sigaction=NULL;
- act.sa_handler=SIG_IGN;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_sigaction = NULL;
+ act.sa_handler = SIG_IGN;
sigemptyset(&act.sa_mask);
- act.sa_flags=SA_RESTART;
+ act.sa_flags = SA_RESTART;
/* ignore SIGPIPE */
- if (sigaction(SIGPIPE,&act,&oldact)!=0)
+ if (sigaction(SIGPIPE, &act, &oldact) != 0)
return -1; /* error setting signal handler */
/* write the buffer */
- rv=write(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
+ rv = write(fp->fd, fp->writebuffer.buffer + fp->writebuffer.start,
+ fp->writebuffer.len);
/* restore the old handler for SIGPIPE */
- if (sigaction(SIGPIPE,&oldact,NULL)!=0)
+ if (sigaction(SIGPIPE, &oldact, NULL) != 0)
return -1; /* error restoring signal handler */
#endif
/* check for errors */
- if ((rv==0)||((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN)))
+ if ((rv == 0) || ((rv < 0) && (errno != EINTR) && (errno != EAGAIN)))
return -1; /* something went wrong with the write */
/* skip the written part in the buffer */
- if (rv>0)
+ if (rv > 0)
{
- fp->writebuffer.start+=rv;
- fp->writebuffer.len-=rv;
+ fp->writebuffer.start += rv;
+ fp->writebuffer.len -= rv;
#ifdef DEBUG_TIO_STATS
- fp->byteswritten+=rv;
+ fp->byteswritten += rv;
#endif /* DEBUG_TIO_STATS */
/* reset start if len is 0 */
- if (fp->writebuffer.len==0)
- fp->writebuffer.start=0;
+ if (fp->writebuffer.len == 0)
+ fp->writebuffer.start = 0;
/* move contents of the buffer to the front if it will save enough room */
- if (fp->writebuffer.start>=(fp->writebuffer.size/4))
+ if (fp->writebuffer.start >= (fp->writebuffer.size / 4))
{
- memmove(fp->writebuffer.buffer,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
- fp->writebuffer.start=0;
+ memmove(fp->writebuffer.buffer,
+ fp->writebuffer.buffer + fp->writebuffer.start,
+ fp->writebuffer.len);
+ fp->writebuffer.start = 0;
}
}
return 0;
/* write all the data in the buffer to the stream */
int tio_flush(TFILE *fp)
{
- struct timeval deadline;
- /* build a time by which we should be finished */
- tio_get_deadline(&deadline,fp->writetimeout);
+ struct timespec deadline = {0, 0};
/* loop until we have written our buffer */
while (fp->writebuffer.len > 0)
{
/* wait until we can write */
- if (tio_wait(fp,0,&deadline))
+ if (tio_wait(fp->fd, POLLOUT, fp->writetimeout, &deadline))
return -1;
/* write one block */
if (tio_writebuf(fp))
{
struct pollfd fds[1];
int rv;
- /* wait for activity */
- fds[0].fd=fp->fd;
- fds[0].events=POLLOUT;
- rv=poll(fds,1,0);
+ /* see if we can write without blocking */
+ fds[0].fd = fp->fd;
+ fds[0].events = POLLOUT;
+ rv = poll(fds, 1, 0);
/* check if any file descriptors were ready (timeout) or we were
interrupted */
- if ((rv==0)||((rv<0)&&(errno==EINTR)))
+ if ((rv == 0) || ((rv < 0) && ((errno == EINTR) || (errno == EAGAIN))))
return 0;
/* any other errors? */
- if (rv<0)
+ if (rv < 0)
return -1;
/* so file descriptor will accept writes */
return tio_writebuf(fp);
size_t fr;
uint8_t *tmp;
size_t newsz;
- const uint8_t *ptr=(const uint8_t *)buf;
+ const uint8_t *ptr = (const uint8_t *)buf;
/* keep filling the buffer until we have bufferred everything */
- while (count>0)
+ while (count > 0)
{
/* figure out free size in buffer */
- fr=fp->writebuffer.size-(fp->writebuffer.start+fp->writebuffer.len);
+ fr = fp->writebuffer.size - (fp->writebuffer.start + fp->writebuffer.len);
if (count <= fr)
{
/* the data fits in the buffer */
- memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,count);
- fp->writebuffer.len+=count;
+ memcpy(fp->writebuffer.buffer + fp->writebuffer.start +
+ fp->writebuffer.len, ptr, count);
+ fp->writebuffer.len += count;
return 0;
}
else if (fr > 0)
{
/* fill the buffer with data that will fit */
- memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,fr);
- fp->writebuffer.len+=fr;
- ptr+=fr;
- count-=fr;
+ memcpy(fp->writebuffer.buffer + fp->writebuffer.start +
+ fp->writebuffer.len, ptr, fr);
+ fp->writebuffer.len += fr;
+ ptr += fr;
+ count -= fr;
}
/* try to flush some of the data that is in the buffer */
if (tio_flush_nonblock(fp))
return -1;
/* if we have room now, try again */
- if (fp->writebuffer.size>(fp->writebuffer.start+fp->writebuffer.len))
+ if (fp->writebuffer.size > (fp->writebuffer.start + fp->writebuffer.len))
continue;
/* try to grow the buffer */
- if (fp->writebuffer.size<fp->writebuffer.maxsize)
+ if (fp->writebuffer.size < fp->writebuffer.maxsize)
{
- newsz=fp->writebuffer.size*2;
- if (newsz>fp->writebuffer.maxsize)
- newsz=fp->writebuffer.maxsize;
- tmp=realloc(fp->writebuffer.buffer,newsz);
- if (tmp!=NULL)
+ newsz = fp->writebuffer.size * 2;
+ if (newsz > fp->writebuffer.maxsize)
+ newsz = fp->writebuffer.maxsize;
+ tmp = realloc(fp->writebuffer.buffer, newsz);
+ if (tmp != NULL)
{
- fp->writebuffer.buffer=tmp;
- fp->writebuffer.size=newsz;
+ fp->writebuffer.buffer = tmp;
+ fp->writebuffer.size = newsz;
continue; /* try again */
}
}
{
int retv;
/* write any buffered data */
- retv=tio_flush(fp);
+ retv = tio_flush(fp);
#ifdef DEBUG_TIO_STATS
/* dump statistics to stderr */
- fprintf(stderr,"DEBUG_TIO_STATS READ=%d WRITTEN=%d\n",fp->bytesread,fp->byteswritten);
+ fprintf(stderr, "DEBUG_TIO_STATS READ=%d WRITTEN=%d\n", fp->bytesread,
+ fp->byteswritten);
#endif /* DEBUG_TIO_STATS */
/* close file descriptor */
if (close(fp->fd))
- retv=-1;
+ retv = -1;
/* free any allocated buffers */
+ memset(fp->readbuffer.buffer, 0, fp->readbuffer.size);
+ memset(fp->writebuffer.buffer, 0, fp->writebuffer.size);
free(fp->readbuffer.buffer);
free(fp->writebuffer.buffer);
/* free the tio struct itself */
void tio_mark(TFILE *fp)
{
/* move any data in the buffer to the start of the buffer */
- if ((fp->readbuffer.start>0)&&(fp->readbuffer.len>0))
+ if ((fp->readbuffer.start > 0) && (fp->readbuffer.len > 0))
{
- memmove(fp->readbuffer.buffer,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
- fp->readbuffer.start=0;
+ memmove(fp->readbuffer.buffer,
+ fp->readbuffer.buffer + fp->readbuffer.start, fp->readbuffer.len);
+ fp->readbuffer.start = 0;
}
/* mark the stream as resettable */
- fp->read_resettable=1;
+ fp->read_resettable = 1;
}
int tio_reset(TFILE *fp)
if (!fp->read_resettable)
return -1;
/* reset the buffer */
- fp->readbuffer.len+=fp->readbuffer.start;
- fp->readbuffer.start=0;
+ fp->readbuffer.len += fp->readbuffer.start;
+ fp->readbuffer.start = 0;
return 0;
}
tio.h - timed io functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008, 2010, 2012 Arthur de Jong
+ Copyright (C) 2007, 2008, 2010, 2012, 2013 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
/* Open a new TFILE based on the file descriptor. The timeout is set for any
operation (value in milliseconds). */
-TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
- size_t initreadsize,size_t maxreadsize,
- size_t initwritesize,size_t maxwritesize)
+TFILE *tio_fdopen(int fd, int readtimeout, int writetimeout,
+ size_t initreadsize, size_t maxreadsize,
+ size_t initwritesize, size_t maxwritesize)
LIKE_MALLOC MUST_USE;
/* Read the specified number of bytes from the stream. */
-int tio_read(TFILE *fp,void *buf,size_t count);
+int tio_read(TFILE *fp, void *buf, size_t count);
/* Read and discard the specified number of bytes from the stream. */
-int tio_skip(TFILE *fp,size_t count);
+int tio_skip(TFILE *fp, size_t count);
/* Read all available data from the stream and empty the read buffer. */
-int tio_skipall(TFILE *fp);
+int tio_skipall(TFILE *fp, int timeout);
/* Write the specified buffer to the stream. */
-int tio_write(TFILE *fp,const void *buf,size_t count);
+int tio_write(TFILE *fp, const void *buf, size_t count);
/* Write out all buffered data to the stream. */
int tio_flush(TFILE *fp);