lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1354 - in nss-pam-ldapd: . debian nss

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd commit: r1354 - in nss-pam-ldapd: . debian nss



Author: arthur
Date: Thu Dec 30 14:13:26 2010
New Revision: 1354
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?view=rev&revision=1354

Log:
integrate Solaris support developed by Ted C. Cheng of Symas Corporation that 
was developed on the -solaris branch

Added:
   nss-pam-ldapd/nss/solnss.c
Modified:
   nss-pam-ldapd/   (props changed)
   nss-pam-ldapd/AUTHORS
   nss-pam-ldapd/HACKING
   nss-pam-ldapd/README
   nss-pam-ldapd/configure.ac
   nss-pam-ldapd/debian/copyright
   nss-pam-ldapd/nss/Makefile.am
   nss-pam-ldapd/nss/common.h
   nss-pam-ldapd/nss/ethers.c
   nss-pam-ldapd/nss/exports.solaris
   nss-pam-ldapd/nss/group.c
   nss-pam-ldapd/nss/hosts.c
   nss-pam-ldapd/nss/netgroup.c
   nss-pam-ldapd/nss/networks.c
   nss-pam-ldapd/nss/passwd.c
   nss-pam-ldapd/nss/protocols.c
   nss-pam-ldapd/nss/prototypes.h
   nss-pam-ldapd/nss/rpc.c
   nss-pam-ldapd/nss/services.c
   nss-pam-ldapd/nss/shadow.c

Modified: nss-pam-ldapd/AUTHORS
==============================================================================
--- nss-pam-ldapd/AUTHORS       Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/AUTHORS       Thu Dec 30 14:13:26 2010        (r1354)
@@ -7,6 +7,7 @@
 West Consulting <info@west.nl>
 Arthur de Jong <arthur@arthurdejong.org>
 Howard Chu <hyc@symas.com>
+Symas Corporation (contributed by Ted C. Cheng <tedcheng@symas.com>)
 
 The following people (in no particular order) have also volunteered their
 time, effort, and ideas to make this software available. If you feel you are
@@ -79,3 +80,4 @@
 Jan Schampera <jan.schampera@web.de>
 Nalin Dahyabhai <nalin@redhat.com>
 Daniel Dehennin <daniel.dehennin@baby-gnu.org>
+Ted C. Cheng <tedcheng@symas.com>

Modified: nss-pam-ldapd/HACKING
==============================================================================
--- nss-pam-ldapd/HACKING       Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/HACKING       Thu Dec 30 14:13:26 2010        (r1354)
@@ -91,7 +91,17 @@
 ==========
 
 The NSS module is implemented in the nss directory. The functions are split
-into files according to the database they support. Functions look like:
+into files according to the database they support. The files support multiple
+NSS implementations.
+
+The NSS interface is specific to the C library that is used. The original
+implementation was for the GNU C Library but now also includes an
+implementation for Solaris' C Library and has some support for FreeBSD.
+
+GNU C Library notes
+-------------------
+
+Function definitions for glibc look like:
 
 _nss_ldap_FUNCTION_r(...)
   This function opens the connection to the nslcd (with a time-out), builds
@@ -99,17 +109,41 @@
   waiting for an answer (again with a time-out)
 
 The complete list of exported functions can be found in exports.linux and
-prototypes.h. The NSS interface seems to be fairly libc-specific and is
-currently tuned towards GNU Libc, although FreeBSD has a port based on this
-code.
+prototypes.h.
 
 Currently a number of macros are used to build most of the function bodies for
 these functions. Part of this is defined in the common/nslcd-prot.h file and
 the NSS-specific stuff is in nss/common.h.
 
+For memory management, the general mechanism that is expected to be used is
+to return NSS_STATUS_TRYAGAIN and set errno to ERANGE. This causes glibc to
+retry the request with a larger buffer.
+
 Some useful links:
 http://www.gnu.org/software/libc/manual/html_node/index.html
 
+Solaris C Library notes
+-----------------------
+
+The Solaris C library uses a different mechanism. For each map a back-end
+object is allocated per thread which is used to do queries. The object is
+created with a constructor (e.g. _nss_ldap_passwd_constr()) that returns a
+back-end that contains a list of function pointer to lookup methods and a
+destructor.
+
+A buffer is passed with every request but a local buffer that is stored in the
+back-end can presumably also be created.
+
+Earlier versions of Solaris expected the NSS functions to return the binary
+representation of the lookups (e.g. struct passwd) but later versions expect a
+string representation of the data to be returned (just like a single line out
+of /etc/passwd was read).
+
+Source and documentation pointers for Solaris NSS:
+http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/nsswitch/
+http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/head/nss_common.h
+http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/head/nss_dbdefs.h
+
 
 PAM MODULE
 ==========

Modified: nss-pam-ldapd/README
==============================================================================
--- nss-pam-ldapd/README        Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/README        Thu Dec 30 14:13:26 2010        (r1354)
@@ -10,7 +10,8 @@
    into a thin NSS part and a server part. Most of the code was rewritten.
 
    The software was renamed to nss-pam-ldapd when PAM code contributed by
-   Howard Chu for the OpenLDAP nssov module was integrated.
+   Howard Chu for the OpenLDAP nssov module was integrated. Solaris
+   compatibility was developed by Ted C. Cheng of Symas Corporation.
 
    http://arthurdejong.org/nss-pam-ldapd/
 
@@ -18,6 +19,7 @@
    Copyright (C) 2006, 2007 West Consulting
    Copyright (C) 2006, 2007, 2008, 2009, 2010 Arthur de Jong
    Copyright (C) 2009 Howard Chu
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public

Modified: nss-pam-ldapd/configure.ac
==============================================================================
--- nss-pam-ldapd/configure.ac  Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/configure.ac  Thu Dec 30 14:13:26 2010        (r1354)
@@ -433,7 +433,10 @@
   AC_MSG_CHECKING([which NSS maps to build])
   if test "x$with_nss_maps" = "xall"
   then
-    
with_nss_maps="aliases,ethers,group,hosts,netgroup,networks,passwd,protocols,rpc,services,shadow"
+    case "$with_nss_flavour" in
+      glibc)   
with_nss_maps="aliases,ethers,group,hosts,netgroup,networks,passwd,protocols,rpc,services,shadow"
 ;;
+      solaris) 
with_nss_maps="ethers,group,hosts,netgroup,networks,passwd,protocols,rpc,services,shadow"
 ;;
+    esac
   fi
   AC_MSG_RESULT($with_nss_maps)
   NSS_MODULE_OBJS="`echo "$with_nss_maps " | sed 's/,/ /g;s/  */.$(OBJEXT) 
/g'`"
@@ -724,6 +727,9 @@
   AM_PATH_PYTHON(2.5)
 fi
 
+AM_CONDITIONAL([NSS_FLAVOUR_GLIBC], [test "x${with_nss_flavour}" = xglibc])
+AM_CONDITIONAL([NSS_FLAVOUR_SOLARIS], [test "x${with_nss_flavour}" = xsolaris])
+
 # generate files
 AC_CONFIG_FILES([Makefile compat/Makefile common/Makefile nss/Makefile
                  pam/Makefile nslcd/Makefile pynslcd/Makefile pynslcd/config.py

Modified: nss-pam-ldapd/debian/copyright
==============================================================================
--- nss-pam-ldapd/debian/copyright      Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/debian/copyright      Thu Dec 30 14:13:26 2010        (r1354)
@@ -7,6 +7,11 @@
 
 In 2006 Arthur de Jong of West Consuling forked the library to split it into a
 thin NSS part and a server part. Most of the code was rewritten.
+
+The software was renamed to nss-pam-ldapd when PAM code contributed by Howard
+Chu for the OpenLDAP nssov module was integrated. Solaris compatibility was
+developed by Ted C. Cheng of Symas Corporation.
+
 http://arthurdejong.org/nss-pam-ldapd/
 
 Arthur de Jong is both the upstream and Debian package maintainer, so there
@@ -20,6 +25,7 @@
   Copyright (C) 2006-2007 West Consulting
   Copyright (C) 2006-2009 Arthur de Jong
   Copyright (C) 2009 Howard Chu
+  Copyright (C) 2010 Symas Corporation
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public

Modified: nss-pam-ldapd/nss/Makefile.am
==============================================================================
--- nss-pam-ldapd/nss/Makefile.am       Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/Makefile.am       Thu Dec 30 14:13:26 2010        (r1354)
@@ -31,8 +31,12 @@
 EXTRA_nss_ldap_so_SOURCES = aliases.c ethers.c group.c hosts.c netgroup.c \
                             networks.c passwd.c protocols.c rpc.c services.c \
                             shadow.c
-nss_ldap_so_DEPENDENCIES = $(NSS_MODULE_OBJS)
-nss_ldap_so_LDADD = $(NSS_MODULE_OBJS) ../common/libtio.a ../common/libprot.a
+nss_ldap_so_LDADD = $(NSS_MODULE_OBJS)
+if NSS_FLAVOUR_SOLARIS
+nss_ldap_so_LDADD += solnss.$(OBJEXT) ../common/libdict.a
+endif
+nss_ldap_so_LDADD += ../common/libtio.a ../common/libprot.a
+nss_ldap_so_DEPENDENCIES = $(nss_ldap_so_LDADD)
 
 EXTRA_DIST = exports.glibc exports.solaris
 

Modified: nss-pam-ldapd/nss/common.h
==============================================================================
--- nss-pam-ldapd/nss/common.h  Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/common.h  Thu Dec 30 14:13:26 2010        (r1354)
@@ -75,7 +75,12 @@
   if (!_nss_ldap_enablelookups) \
     return NSS_STATUS_UNAVAIL;
 
-/* check validity of passed buffer */
+#ifdef NSS_FLAVOUR_GLIBC
+
+/* extra definitions we need (nothing for Glibc) */
+#define NSS_EXTRA_DEFS ;
+
+/* check validity of passed buffer (Glibc flavour) */
 #define NSS_BUFCHECK \
   if ((buffer==NULL)||(buflen<=0)) \
   { \
@@ -83,6 +88,38 @@
       return NSS_STATUS_UNAVAIL; \
   }
 
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+/* extra definitions we need (Solaris NSS functions don't pass errno) */
+#define NSS_EXTRA_DEFS \
+  int *errnop=&(errno);
+
+/* check validity of passed buffer (Solaris flavour) */
+#define NSS_BUFCHECK \
+  if ((NSS_ARGS(args)->buf.buffer==NULL)||(NSS_ARGS(args)->buf.buflen<=0)) \
+  { \
+      NSS_ARGS(args)->erange=1; \
+      return NSS_STATUS_TRYAGAIN; \
+  }
+
+/* this is the backend structure for Solaris */
+struct nss_ldap_backend
+{
+  nss_backend_op_t *ops; /* function-pointer table */
+  int n_ops; /* number of function pointers */
+  TFILE *fp; /* the file pointer for {set,get,end}ent() functions */
+};
+
+/* constructor for LDAP backends */
+nss_backend_t *nss_ldap_constructor(nss_backend_op_t *ops,size_t sizeofops);
+
+/* destructor for LDAP backends */
+nss_status_t nss_ldap_destructor(nss_backend_t *be,void UNUSED(*args));
+
+#endif /* NSS_FLAVOUR_SOLARIS */
+
 /* The following macros to automatically generate get..byname(),
    get..bynumber(), setent(), getent() and endent() function
    bodies. These functions have very common code so this can
@@ -100,6 +137,7 @@
   TFILE *fp; \
   int32_t tmpint32; \
   nss_status_t retv; \
+  NSS_EXTRA_DEFS; \
   NSS_AVAILCHECK; \
   NSS_BUFCHECK; \
   /* open socket and write request */ \
@@ -144,6 +182,7 @@
 #define NSS_GETENT(fp,action,readfn) \
   int32_t tmpint32; \
   nss_status_t retv; \
+  NSS_EXTRA_DEFS; \
   NSS_AVAILCHECK; \
   NSS_BUFCHECK; \
   /* check that we have a valid file descriptor */ \

Modified: nss-pam-ldapd/nss/ethers.c
==============================================================================
--- nss-pam-ldapd/nss/ethers.c  Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/ethers.c  Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -41,6 +42,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* map a hostname to the corresponding ethernet address */
 nss_status_t _nss_ldap_gethostton_r(
         const char *name,struct etherent *result,
@@ -84,3 +87,98 @@
 {
   NSS_ENDENT(etherentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifndef NSS_BUFLEN_ETHERS
+#define NSS_BUFLEN_ETHERS 1024
+#endif /* NSS_BUFLEN_ETHERS */
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_etherstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct etherent result;
+  nss_status_t retv;
+  char *buffer;
+  int res;
+  /* read the etherent into a temporary buffer */
+  buffer=(char *)malloc(args->buf.buflen);
+  if (buffer==NULL)
+    return NSS_STATUS_UNAVAIL;
+  retv=read_etherent(fp,&result,buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+  {
+    free(buffer);
+    return retv;
+  }
+  /* make a string representation */
+  res=snprintf(args->buf.buffer,args->buf.buflen,
+               "%s %s",ether_ntoa(&result.e_addr),result.e_name);
+  free(buffer);
+  if ((res<0)||(res>=args->buf.buflen))
+    return NSS_STATUS_TRYAGAIN;
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_etherent(fp,(struct etherent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_etherstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_etherent(fp,(struct etherent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+/* map a hostname to the corresponding ethernet address */
+static nss_status_t ethers_gethostton(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_ETHER_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+/* map an ethernet address to the corresponding hostname */
+static nss_status_t ethers_getntohost(nss_backend_t UNUSED(*be),void *args)
+{
+  struct ether_addr *addr=(struct ether_addr *)(NSS_ARGS(args)->key.ether);
+  NSS_BYTYPE(NSLCD_ACTION_ETHER_BYETHER,
+             *addr,uint8_t[6],
+             READ_RESULT(fp));
+}
+
+static nss_status_t ethers_destructor(nss_backend_t *be,void UNUSED(*args))
+{
+  free(be);
+  return NSS_STATUS_SUCCESS;
+}
+
+static nss_backend_op_t ethers_ops[]={
+  ethers_destructor,
+  ethers_gethostton,
+  ethers_getntohost
+};
+
+nss_backend_t *_nss_ldap_ethers_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  nss_backend_t *be;
+  if (!(be=(nss_backend_t *)malloc(sizeof(*be))))
+    return NULL;
+  be->ops=ethers_ops;
+  be->n_ops=sizeof(ethers_ops)/sizeof(nss_backend_op_t);
+  return be;
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/exports.solaris
==============================================================================
--- nss-pam-ldapd/nss/exports.solaris   Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/exports.solaris   Thu Dec 30 14:13:26 2010        (r1354)
@@ -1,20 +1,22 @@
-# $Id: exports.solaris,v 1.1 2010-08-07 00:24:21 tedcheng Exp $
-
 nss_ldap.so.1 {
+
   # published NSS service functions
   global:
-    # Published NSS service module interfaces
-       # _nss_ldap_bootparams_constr;
-       _nss_ldap_ethers_constr;
-       _nss_ldap_group_constr;
-       _nss_ldap_hosts_constr;
-       _nss_ldap_networks_constr;
-       _nss_ldap_protocols_constr;
-       _nss_ldap_passwd_constr;
-       _nss_ldap_rpc_constr;
-       _nss_ldap_services_constr;
-       _nss_ldap_shadow_constr;
-       _nss_ldap_netgroup_constr;
+
+    # flag to enable or disable lookups
+    _nss_ldap_enablelookups;
+
+    # published NSS service module constructors
+    _nss_ldap_ethers_constr;
+    _nss_ldap_group_constr;
+    _nss_ldap_hosts_constr;
+    _nss_ldap_networks_constr;
+    _nss_ldap_protocols_constr;
+    _nss_ldap_passwd_constr;
+    _nss_ldap_rpc_constr;
+    _nss_ldap_services_constr;
+    _nss_ldap_shadow_constr;
+    _nss_ldap_netgroup_constr;
 
   # everything else should not be exported
   local:

Modified: nss-pam-ldapd/nss/group.c
==============================================================================
--- nss-pam-ldapd/nss/group.c   Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/group.c   Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2009, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -53,8 +54,10 @@
   int32_t res=(int32_t)NSLCD_RESULT_BEGIN;
   int32_t tmpint32,tmp2int32,tmp3int32;
   gid_t gid;
+#ifdef NSS_FLAVOUR_GLIBC
   gid_t *newgroups;
   long int newsize;
+#endif /* NSS_FLAVOUR_GLIBC */
   /* loop over results */
   while (res==(int32_t)NSLCD_RESULT_BEGIN)
   {
@@ -73,6 +76,7 @@
       if ( (limit>0) && (*start>=limit) )
         return NSS_STATUS_TRYAGAIN;
       /* check if our buffer is large enough */
+#ifdef NSS_FLAVOUR_GLIBC
       if ((*start)>=(*size))
       {
         /* for some reason Glibc expects us to grow the array (completely
@@ -88,6 +92,7 @@
         *groupsp=newgroups;
         *size=newsize;
       }
+#endif /* NSS_FLAVOUR_GLIBC */
       /* add gid to list */
       (*groupsp)[(*start)++]=gid;
     }
@@ -100,6 +105,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a group entry by name */
 nss_status_t _nss_ldap_getgrnam_r(
         const char *name,struct group *result,
@@ -171,3 +178,126 @@
 #undef buffer
 #undef buflen
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_groupstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct group result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  /* read the group into a temporary buffer */
+  buffer=(char *)malloc(args->buf.buflen);
+  if (buffer==NULL)
+    return NSS_STATUS_UNAVAIL;
+  retv=read_group(fp,&result,buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+  {
+    free(buffer);
+    return retv;
+  }
+  /* make a string representation */
+  snprintf(args->buf.buffer,args->buf.buflen,
+           "%s:%s:%d:",result.gr_name,result.gr_passwd,(int)result.gr_gid);
+  args->buf.buffer[args->buf.buflen-1]='\0';
+  if (result.gr_mem)
+    for (i=0;result.gr_mem[i];i++)
+    {
+      if (i)
+        
strncat(args->buf.buffer,args->buf.buflen-strlen(args->buf.buffer)-1,",");
+      
strncat(args->buf.buffer,args->buf.buflen-strlen(args->buf.buffer)-1,result.gr_mem[i]);
+    }
+  free(buffer);
+  /* check if buffer overflowed */
+  if (strlen(args->buf.buffer)>=args->buf.buffer-1)
+    return NSS_STATUS_TRYAGAIN;
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_group(fp,(struct group 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_groupstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_group(fp,(struct group 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t group_getgrnam(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_GROUP_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t group_getgrgid(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYTYPE(NSLCD_ACTION_GROUP_BYGID,
+             NSS_ARGS(args)->key.gid,gid_t,
+             READ_RESULT(fp));
+}
+
+static nss_status_t group_setgrent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t group_getgrent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_GROUP_ALL,
+             READ_RESULT((LDAP_BE(be)->fp)));
+}
+
+static nss_status_t group_endgrent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+/*
+static nss_status_t get_initgroups_dyn(
+        const char *user,gid_t skipgroup,long int *start,
+        gid_t **groupsp,long int limit,int *errnop)
+*/
+static nss_status_t group_getgroupsbymember(nss_backend_t UNUSED(*be),void 
*args)
+{
+  struct nss_groupsbymem *argp=(struct nss_groupsbymem *)args;
+  long int start=(long int)argp->numgids;
+  gid_t skipgroup=(start>0)?argp->gid_array[0]:(gid_t)-1;
+  NSS_BYNAME(NSLCD_ACTION_GROUP_BYMEMBER,
+             argp->username,
+             read_gids(fp,skipgroup,&start,NULL,(gid_t 
**)&argp->gid_array,argp->maxgids,&errno);
+             argp->numgids=(int)start;);
+}
+
+static nss_backend_op_t group_ops[]={
+  nss_ldap_destructor,
+  group_endgrent,
+  group_setgrent,
+  group_getgrent,
+  group_getgrnam,
+  group_getgrgid,
+  group_getgroupsbymember
+};
+
+nss_backend_t *_nss_ldap_group_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(group_ops,sizeof(group_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/hosts.c
==============================================================================
--- nss-pam-ldapd/nss/hosts.c   Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/hosts.c   Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,9 @@
 
 #include <string.h>
 #include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "prototypes.h"
 #include "common.h"
@@ -167,6 +171,8 @@
   WRITE_INT32(fp,len); \
   WRITE(fp,addr,len);
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* this function looks up a single host entry and returns all the addresses
    associated with the host in a single address familiy
    name            - IN  - hostname to lookup
@@ -231,3 +237,146 @@
 {
   NSS_ENDENT(hostentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+struct nss_ldap_hosts_backend
+{
+  nss_backend_op_t *ops;
+  int n_ops;
+  TFILE *fp;
+};
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_hoststring(TFILE *fp,nss_XbyY_args_t *args,int 
erronempty)
+{
+  struct hostent result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  /* read the hostent */
+  if (erronempty)
+    
retv=read_hostent_erronempty(fp,NSS_ARGS(args)->key.hostaddr.type,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
+  else
+    
retv=read_hostent_nextonempty(fp,NSS_ARGS(args)->key.hostaddr.type,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  if (result.h_addr_list)
+  {
+    struct in_addr in;
+    (void)memcpy(&in.s_addr,result.h_addr_list[0],sizeof(in.s_addr));
+    sprintf(buffer,"%s %s",inet_ntoa(in),result.h_name);
+    if (result.h_aliases)
+    {
+      int j;
+      for (j=0;result.h_aliases[j];j++)
+      {
+        strcat(buffer,"  ");
+        strcat(buffer,result.h_aliases[j]);
+      }
+    }
+    for (i=1;result.h_addr_list[i];i++)
+    {
+      (void)memcpy(&in.s_addr,result.h_addr_list[i],sizeof(in.s_addr));
+      strcat(buffer,"\n");
+      strcat(buffer,inet_ntoa(in));
+      strcat(buffer," ");
+      strcat(buffer,result.h_name);
+      /* TODO: aliases only supplied to the first address */
+      /* need review */
+    }
+  }
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT_ERRONEMPTY(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_hostent_erronempty(fp,NSS_ARGS(args)->key.hostaddr.type,(struct 
hostent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno)):
 \
+    read_hoststring(fp,args,1); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#define READ_RESULT_NEXTONEMPTY(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_hostent_nextonempty(fp,NSS_ARGS(args)->key.hostaddr.type,(struct 
hostent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno)):
 \
+    read_hoststring(fp,args,0); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT_ERRONEMPTY(fp) \
+  read_hostent_erronempty(fp,NSS_ARGS(args)->key.hostaddr.type,(struct hostent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#define READ_RESULT_NEXTONEMPTY(fp) \
+  read_hostent_nextonempty(fp,NSS_ARGS(args)->key.hostaddr.type,(struct 
hostent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+/* hack to set the correct errno and h_errno */
+#define h_errnop &(NSS_ARGS(args)->h_errno)
+
+static nss_status_t hosts_gethostbyname(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_HOST_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT_ERRONEMPTY(fp));
+}
+
+static nss_status_t hosts_gethostbyaddr(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYGEN(NSLCD_ACTION_HOST_BYADDR,
+            
WRITE_ADDRESS(fp,NSS_ARGS(args)->key.hostaddr.type,NSS_ARGS(args)->key.hostaddr.len,NSS_ARGS(args)->key.hostaddr.addr),
+            READ_RESULT_ERRONEMPTY(fp));
+}
+
+static nss_status_t hosts_sethostent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t hosts_gethostent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_HOST_ALL,
+             READ_RESULT_NEXTONEMPTY(LDAP_BE(be)->fp));
+}
+
+static nss_status_t hosts_endhostent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t hosts_ops[]={
+  nss_ldap_destructor,
+  hosts_endhostent,
+  hosts_sethostent,
+  hosts_gethostent,
+  hosts_gethostbyname,
+  hosts_gethostbyaddr
+};
+
+nss_backend_t *_nss_ldap_hosts_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(hosts_ops,sizeof(hosts_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/netgroup.c
==============================================================================
--- nss-pam-ldapd/nss/netgroup.c        Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/netgroup.c        Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -29,6 +30,7 @@
 #include "prototypes.h"
 #include "common.h"
 #include "compat/attrs.h"
+#include "common/set.h"
 
 /* we redefine this here because we need to return NSS_STATUS_RETURN
    instead of NSS_STATUS_NOTFOUND */
@@ -86,6 +88,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* thread-local file pointer to an ongoing request */
 static __thread TFILE *netgrentfp;
 
@@ -123,3 +127,206 @@
 {
   NSS_ENDENT(netgrentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+/* this is the backend structure for the {set,get,end}ent() functions */
+struct setnetgrent_backend
+{
+  nss_backend_op_t *ops; /* function-pointer table */
+  int n_ops; /* number of function pointers */
+  TFILE *fp; /* the file pointer for {set,get,end}ent() functions */
+  SET *seen_groups; /* netgroups seen, for loop detection */
+  SET *unseen_groups; /* netgroups that need to be chased */
+};
+
+/* easy way to get sets from back-end */
+#define NETGROUP_BE(be) ((struct setnetgrent_backend*)(be))
+
+/* access arguments */
+#define SETNETGRENT_ARGS(args) ((struct nss_setnetgrent_args *)(args))
+#define GETNETGRENT_ARGS(args) ((struct nss_getnetgrent_args *)(args))
+
+/* return a netgroup that has not been traversed */
+static char *find_unseen_netgroup(nss_backend_t *be)
+{
+  char *group;
+  while (1)
+  {
+    group=set_pop(NETGROUP_BE(be)->unseen_groups);
+    if (group==NULL)
+      return NULL;
+    if (!set_contains(NETGROUP_BE(be)->seen_groups,group))
+    {
+      set_add(NETGROUP_BE(be)->seen_groups,group);
+      return group;
+    }
+  }
+}
+
+static nss_status_t netgroup_nslcd_setnetgrent(nss_backend_t *be,const char 
*group)
+{
+  /* we cannot use NSS_SETENT() here because we have a parameter that is only
+     available in this function */
+  int32_t tmpint32;
+  int errnocp;
+  int *errnop;
+  errnop=&errnocp;
+  /* check parameter */
+  if ((group==NULL)||(group[0]=='\0'))
+    return NSS_STATUS_UNAVAIL;
+  /* open a new stream and write the request */
+  NSLCD_REQUEST(NETGROUP_BE(be)->fp,NSLCD_ACTION_NETGROUP_BYNAME,
+                WRITE_STRING(NETGROUP_BE(be)->fp,group));
+  return NSS_STATUS_SUCCESS;
+}
+
+static nss_status_t netgroup_nslcd_getnetgrent(nss_backend_t *be,struct 
__netgrent *result,char *buffer,size_t buflen,void *args)
+{
+  NSS_GETENT(NETGROUP_BE(be)->fp,NSLCD_ACTION_NETGROUP_BYNAME,
+             read_netgrent(NETGROUP_BE(be)->fp,result,buffer,buflen,errnop));
+}
+
+static nss_status_t netgroup_setnetgrent_setnetgrent(nss_backend_t 
UNUSED(*be),void UNUSED(*args))
+{
+  return NSS_STATUS_SUCCESS;
+}
+
+static nss_status_t netgroup_setnetgrent_getnetgrent(nss_backend_t *be,void 
*args)
+{
+  struct __netgrent result;
+  char *group=NULL;
+  int done=0;
+  nss_status_t status,rc;
+  GETNETGRENT_ARGS(args)->status=NSS_NETGR_NO;
+  while (!done)
+  {
+    
status=netgroup_nslcd_getnetgrent(be,&result,GETNETGRENT_ARGS(args)->buffer,
+                                         GETNETGRENT_ARGS(args)->buflen,args);
+    if (status!=NSS_STATUS_SUCCESS)
+    {
+      if (errno==ENOENT)
+      {
+        /* done with the current netgroup */
+        /* explore nested netgroup,if any */
+        int found=0;
+        while (!found)
+        {
+          /* find a nested netgroup to pursue further */
+          group=find_unseen_netgroup(be);
+          if (group==NULL)
+          {
+            /* no more netgroup */
+            found=1; done=1;
+            errno=ENOENT;
+          }
+          else
+          {
+            rc=netgroup_nslcd_setnetgrent(be,group);
+            if (rc==NSS_STATUS_SUCCESS)
+              found=1;
+            free(group);
+            group=NULL;
+          }
+        } /* while !found */
+      }
+      else
+      { /* err!=ENOENT */
+        done=1;
+      }
+    }
+    else
+    { /* status==NSS_STATUS_SUCCESS */
+      if (result.type==group_val)
+      {
+        /* a netgroup nested within the current netgroup */
+        set_add(NETGROUP_BE(be)->unseen_groups,result.val.group);
+      }
+      else if (result.type==triple_val)
+      {
+        GETNETGRENT_ARGS(args)->retp[NSS_NETGR_MACHINE]=result.val.triple.host;
+        GETNETGRENT_ARGS(args)->retp[NSS_NETGR_USER]=result.val.triple.user;
+        
GETNETGRENT_ARGS(args)->retp[NSS_NETGR_DOMAIN]=result.val.triple.domain;
+        GETNETGRENT_ARGS(args)->status=NSS_NETGR_FOUND;
+        done=1;
+      }
+      else
+      {
+        /* NSS_STATUS_SUCCESS,but type is not group_val or triple_val */
+        /* should not be here,log a message */
+        status=NSS_STATUS_NOTFOUND;
+        done=1;
+      }
+    }
+  } /* while !done */
+  return status;
+}
+
+static nss_status_t netgroup_setnetgrent_endnetgrent(nss_backend_t 
UNUSED(*be),void UNUSED(*args))
+{
+  NSS_ENDENT(NETGROUP_BE(be)->fp);
+}
+
+static nss_status_t netgroup_setnetgrent_destructor(nss_backend_t *be,void 
*UNUSED(args))
+{
+  struct setnetgrent_backend *ngbe=(struct setnetgrent_backend *)be;
+  if (ngbe->fp!=NULL)
+    (void)tio_close(ngbe->fp);
+  set_free(ngbe->seen_groups);
+  set_free(ngbe->unseen_groups);
+  free(ngbe);
+  return NSS_STATUS_SUCCESS;
+}
+
+static nss_backend_op_t netgroup_setnetgrent_ops[]={
+  netgroup_setnetgrent_destructor,
+  netgroup_setnetgrent_endnetgrent,
+  netgroup_setnetgrent_setnetgrent,
+  netgroup_setnetgrent_getnetgrent,
+};
+
+static nss_status_t netgroup_setnetgrent_constructor(nss_backend_t *be,void 
*args)
+{
+  struct setnetgrent_backend *ngbe;
+  nss_status_t retv;
+  NSS_AVAILCHECK;
+  SETNETGRENT_ARGS(args)->iterator=NULL;        /* initialize */
+  /* allocate a back-end specific to this request */
+  ngbe=(struct setnetgrent_backend *)malloc(sizeof(struct 
setnetgrent_backend));
+  if (ngbe==NULL)
+    return NSS_STATUS_UNAVAIL;
+  ngbe->ops=netgroup_setnetgrent_ops;
+  ngbe->n_ops=sizeof(netgroup_setnetgrent_ops)/sizeof(nss_backend_op_t);
+  ngbe->fp=NULL;
+  ngbe->seen_groups=set_new();
+  ngbe->unseen_groups=set_new();
+  /* start the first search */
+  retv=netgroup_nslcd_setnetgrent(be,SETNETGRENT_ARGS(args)->netgroup);
+  if (retv!=NSS_STATUS_SUCCESS)
+  {
+    netgroup_setnetgrent_destructor(be,args);
+    return retv;
+  }
+  /* return the new back-end */
+  SETNETGRENT_ARGS(args)->iterator=(nss_backend_t *)ngbe;
+  return NSS_STATUS_SUCCESS;
+}
+
+static nss_backend_op_t netgroup_ops[]={
+  nss_ldap_destructor,
+  NULL,
+  NULL,
+  NULL,
+  NULL,/* TODO:_nss_ldap_netgr_in,*/
+  netgroup_setnetgrent_constructor
+};
+
+nss_backend_t *_nss_ldap_netgroup_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(netgroup_ops,sizeof(netgroup_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/networks.c
==============================================================================
--- nss-pam-ldapd/nss/networks.c        Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/networks.c        Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,9 @@
 
 #include <string.h>
 #include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "prototypes.h"
 #include "common.h"
@@ -107,6 +111,8 @@
   WRITE_INT32(fp,4); \
   WRITE_INT32(fp,htonl(addr));
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a network entry by name */
 nss_status_t _nss_ldap_getnetbyname_r(
         const char *name,struct netent *result,
@@ -151,3 +157,108 @@
 {
   NSS_ENDENT(netentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_netentstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct netent result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  struct in_addr priv_in_addr;
+  /* read the netent */
+  
retv=read_netent(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  priv_in_addr.s_addr = result.n_net;
+  sprintf(buffer,"%s %s",result.n_name,inet_ntoa(priv_in_addr)); /* 
ipNetworkNumber */
+  if (result.n_aliases)
+    for (i=0;result.n_aliases[i];i++)
+    {
+      strcat(buffer," ");
+      strcat(buffer,result.n_aliases[i]);
+    }
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_netent(fp,(struct netent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno)):
 \
+    read_netentstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_netent(fp,(struct netent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno,&(NSS_ARGS(args)->h_errno));
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+/* more of a dirty hack */
+#define h_errnop (&(NSS_ARGS(args)->h_errno))
+
+static nss_status_t networks_getnetbyname(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_NETWORK_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t networks_getnetbyaddr(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYGEN(NSLCD_ACTION_NETWORK_BYADDR,
+            WRITE_ADDRESS(fp,NSS_ARGS(args)->key.netaddr.net),
+            READ_RESULT(fp));
+}
+
+static nss_status_t networks_setnetent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t networks_getnetent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_NETWORK_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+static nss_status_t networks_endnetent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t networks_ops[]={
+  nss_ldap_destructor,
+  networks_endnetent,
+  networks_setnetent,
+  networks_getnetent,
+  networks_getnetbyname,
+  networks_getnetbyaddr
+};
+
+nss_backend_t *_nss_ldap_networks_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(networks_ops,sizeof(networks_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/passwd.c
==============================================================================
--- nss-pam-ldapd/nss/passwd.c  Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/passwd.c  Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -46,6 +47,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a single passwd entry by name */
 nss_status_t _nss_ldap_getpwnam_r(
         const char *name,struct passwd *result,
@@ -89,3 +92,101 @@
 {
   NSS_ENDENT(pwentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_passwdstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct passwd result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  /* read the passwd */
+  
retv=read_passwd(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+   sprintf(buffer,"%s:%s:%d:%d:%s:%s:%s",
+     
result.pw_name,result.pw_passwd,(int)result.pw_uid,(int)result.pw_gid,result.pw_gecos,
+     result.pw_dir,result.pw_shell);
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_passwd(fp,(struct passwd 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_passwdstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_passwd(fp,(struct passwd 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t passwd_getpwnam(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_PASSWD_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t passwd_getpwuid(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYTYPE(NSLCD_ACTION_PASSWD_BYUID,
+             NSS_ARGS(args)->key.uid,uid_t,
+             READ_RESULT(fp));
+}
+
+/* open a connection to the nslcd and write the request */
+static nss_status_t passwd_setpwent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+/* read password data from an opened stream */
+static nss_status_t passwd_getpwent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_PASSWD_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+/* close the stream opened with setpwent() above */
+static nss_status_t passwd_endpwent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t passwd_ops[]={
+  nss_ldap_destructor,
+  passwd_endpwent,
+  passwd_setpwent,
+  passwd_getpwent,
+  passwd_getpwnam,
+  passwd_getpwuid
+};
+
+nss_backend_t *_nss_ldap_passwd_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(passwd_ops,sizeof(passwd_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/protocols.c
==============================================================================
--- nss-pam-ldapd/nss/protocols.c       Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/protocols.c       Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -42,6 +43,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a protocol entry by name */
 nss_status_t _nss_ldap_getprotobyname_r(
         const char *name,struct protoent *result,
@@ -85,3 +88,103 @@
 {
   NSS_ENDENT(protoentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_protostring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct protoent result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  /* read the protoent */
+  
retv=read_protoent(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  sprintf(buffer,"%s\t\t%d",result.p_name,result.p_proto);
+  if (result.p_aliases)
+    for (i=0; result.p_aliases[i]; i++)
+    {
+      strcat(buffer," ");
+      strcat(buffer,result.p_aliases[i]);
+    }
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_protoent(fp,(struct protoent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_protostring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_protoent(fp,(struct protoent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t protocols_getprotobyname(nss_backend_t UNUSED(*be),void 
*args)
+{
+  NSS_BYNAME(NSLCD_ACTION_PROTOCOL_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t protocols_getprotobynumber(nss_backend_t UNUSED(*be),void 
*args)
+{
+  NSS_BYINT32(NSLCD_ACTION_PROTOCOL_BYNUMBER,
+              NSS_ARGS(args)->key.number,
+              READ_RESULT(fp));
+}
+
+static nss_status_t protocols_setprotoent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t protocols_getprotoent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_PROTOCOL_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+static nss_status_t protocols_endprotoent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t protocols_ops[]={
+  nss_ldap_destructor,
+  protocols_endprotoent,
+  protocols_setprotoent,
+  protocols_getprotoent,
+  protocols_getprotobyname,
+  protocols_getprotobynumber
+};
+
+nss_backend_t *_nss_ldap_protocols_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(protocols_ops,sizeof(protocols_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/prototypes.h
==============================================================================
--- nss-pam-ldapd/nss/prototypes.h      Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/prototypes.h      Thu Dec 30 14:13:26 2010        (r1354)
@@ -29,6 +29,8 @@
    NSS_STATUS_UNAVAIL */
 extern int _nss_ldap_enablelookups;
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /*
    These are prototypes for functions exported from the ldap NSS module.
    For more complete definitions of these functions check the GLIBC
@@ -117,4 +119,26 @@
 nss_status_t _nss_ldap_getspent_r(struct spwd *result,char *buffer,size_t 
buflen,int *errnop);
 nss_status_t _nss_ldap_endspent(void);
 
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+/* helper marcos to do casts */
+#define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
+#define LDAP_BE(be) ((struct nss_ldap_backend*)(be))
+
+/* these are the constructors we provide */
+nss_backend_t *_nss_ldap_ethers_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_group_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_hosts_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_netgroup_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_networks_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_passwd_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_protocols_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_rpc_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_services_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+nss_backend_t *_nss_ldap_shadow_constr(const char *db_name,const char 
*src_name,const char *cfg_args);
+
+#endif /* NSS_FLAVOUR_SOLARIS */
+
 #endif /* not NSS__PROTOTYPES_H */

Modified: nss-pam-ldapd/nss/rpc.c
==============================================================================
--- nss-pam-ldapd/nss/rpc.c     Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/rpc.c     Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -42,6 +43,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a rpc entry by name */
 nss_status_t _nss_ldap_getrpcbyname_r(
         const char *name,struct rpcent *result,
@@ -85,3 +88,103 @@
 {
   NSS_ENDENT(rpcentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_rpcstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct rpcent result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  /* read the rpcent */
+  
retv=read_rpcent(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  sprintf(buffer,"%s %d",result.r_name,result.r_number);
+  if (result.r_aliases)
+    for (i=0; result.r_aliases[i]; i++)
+    {
+      strcat(buffer," ");
+      strcat(buffer,result.r_aliases[i]);
+    }
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_rpcent(fp,(struct rpcent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_rpcstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_rpcent(fp,(struct rpcent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t rpc_getrpcbyname(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_RPC_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t rpc_getrpcbynumber(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYINT32(NSLCD_ACTION_RPC_BYNUMBER,
+              NSS_ARGS(args)->key.number,
+              READ_RESULT(fp));
+}
+
+static nss_status_t rpc_setrpcent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t rpc_getrpcent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_RPC_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+static nss_status_t rpc_endrpcent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t rpc_ops[]={
+  nss_ldap_destructor,
+  rpc_endrpcent,
+  rpc_setrpcent,
+  rpc_getrpcent,
+  rpc_getrpcbyname,
+  rpc_getrpcbynumber
+};
+
+nss_backend_t *_nss_ldap_rpc_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(rpc_ops,sizeof(rpc_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/services.c
==============================================================================
--- nss-pam-ldapd/nss/services.c        Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/services.c        Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -46,6 +47,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a service entry by name and protocol */
 nss_status_t _nss_ldap_getservbyname_r(
         const char *name,const char *protocol,struct servent *result,
@@ -89,3 +92,105 @@
 {
   NSS_ENDENT(serventfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_servstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct servent result;
+  nss_status_t retv;
+  char *buffer;
+  size_t buflen;
+  int i;
+  /* read the servent */
+  
retv=read_servent(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  sprintf(buffer,"%s %d/%s",result.s_name,result.s_port,result.s_proto);
+  if (result.s_aliases)
+    for (i=0;result.s_aliases[i];i++)
+    {
+      strcat(buffer," ");
+      strcat(buffer,result.s_aliases[i]);
+    }
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_servent(fp,(struct servent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_servstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_servent(fp,(struct servent 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t services_getservbyname(nss_backend_t UNUSED(*be),void 
*args)
+{
+  NSS_BYGEN(NSLCD_ACTION_SERVICE_BYNAME,
+            WRITE_STRING(fp,NSS_ARGS(args)->key.serv.serv.name);
+            WRITE_STRING(fp,NSS_ARGS(args)->key.serv.proto),
+            READ_RESULT(fp));
+}
+
+static nss_status_t services_getservbyport(nss_backend_t UNUSED(*be),void 
*args)
+{
+  NSS_BYGEN(NSLCD_ACTION_SERVICE_BYNUMBER,
+            WRITE_INT32(fp,ntohs(NSS_ARGS(args)->key.serv.serv.port));
+            WRITE_STRING(fp,NSS_ARGS(args)->key.serv.proto),
+            READ_RESULT(fp));
+}
+
+static nss_status_t services_setservent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t services_getservent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_SERVICE_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+static nss_status_t services_endservent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t services_ops[]={
+  nss_ldap_destructor,
+  services_endservent,
+  services_setservent,
+  services_getservent,
+  services_getservbyname,
+  services_getservbyport
+};
+
+nss_backend_t *_nss_ldap_services_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(services_ops,sizeof(services_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Modified: nss-pam-ldapd/nss/shadow.c
==============================================================================
--- nss-pam-ldapd/nss/shadow.c  Thu Dec 30 13:58:29 2010        (r1353)
+++ nss-pam-ldapd/nss/shadow.c  Thu Dec 30 14:13:26 2010        (r1354)
@@ -3,6 +3,7 @@
 
    Copyright (C) 2006 West Consulting
    Copyright (C) 2006, 2007, 2008, 2010 Arthur de Jong
+   Copyright (C) 2010 Symas Corporation
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -48,6 +49,8 @@
   return NSS_STATUS_SUCCESS;
 }
 
+#ifdef NSS_FLAVOUR_GLIBC
+
 /* get a shadow entry by name */
 nss_status_t _nss_ldap_getspnam_r(
         const char *name,struct spwd *result,
@@ -81,3 +84,124 @@
 {
   NSS_ENDENT(spentfp);
 }
+
+#endif /* NSS_FLAVOUR_GLIBC */
+
+#ifdef NSS_FLAVOUR_SOLARIS
+
+#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
+
+static nss_status_t read_spwdstring(TFILE *fp,nss_XbyY_args_t *args)
+{
+  struct spwd result;
+  nss_status_t retv;
+  char *buffer;
+  char field_buf[128];
+  size_t buflen;
+  /* read the spwd */
+  
retv=read_spwd(fp,&result,NSS_ARGS(args)->buf.buffer,args->buf.buflen,&errno);
+  if (retv!=NSS_STATUS_SUCCESS)
+    return retv;
+  /* allocate a temporary buffer */
+  buflen=args->buf.buflen;
+  buffer=(char *)malloc(buflen);
+  /* build the formatted string */
+  /* FIXME: implement proper buffer size checking */
+  sprintf(buffer,"%s:%s:",result.sp_namp,result.sp_pwdp);
+  if (result.sp_lstchg >= 0)
+    sprintf(field_buf,"%d:",result.sp_lstchg);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_min >= 0)
+    sprintf(field_buf,"%d:",result.sp_min);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_max >= 0)
+    sprintf(field_buf,"%d:",result.sp_max);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_warn >= 0)
+    sprintf(field_buf,"%d:",result.sp_warn);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_inact >= 0)
+    sprintf(field_buf,"%d:",result.sp_inact);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_expire >= 0)
+    sprintf(field_buf,"%d:",result.sp_expire);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  if (result.sp_flag >= 0)
+    sprintf(field_buf,"%x",result.sp_flag);
+  else
+    sprintf(field_buf,":");
+  strcat(buffer,field_buf);
+  /* copy the result back to the result buffer and free the temporary one */
+  strcpy(NSS_ARGS(args)->buf.buffer,buffer);
+  free(buffer);
+  NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer;
+  NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer);
+  return NSS_STATUS_SUCCESS;
+}
+
+#define READ_RESULT(fp) \
+  NSS_ARGS(args)->buf.result? \
+    read_spwd(fp,(struct spwd 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno):
 \
+    read_spwdstring(fp,args); \
+  if ((NSS_ARGS(args)->buf.result)&&(retv==NSS_STATUS_SUCCESS)) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+#define READ_RESULT(fp) \
+  read_spwd(fp,(struct spwd 
*)NSS_ARGS(args)->buf.result,NSS_ARGS(args)->buf.buffer,NSS_ARGS(args)->buf.buflen,&errno);
 \
+  if (retv==NSS_STATUS_SUCCESS) \
+    NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result;
+
+#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
+
+static nss_status_t shadow_getspnam(nss_backend_t UNUSED(*be),void *args)
+{
+  NSS_BYNAME(NSLCD_ACTION_SHADOW_BYNAME,
+             NSS_ARGS(args)->key.name,
+             READ_RESULT(fp));
+}
+
+static nss_status_t shadow_setspent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_SETENT(LDAP_BE(be)->fp);
+}
+
+static nss_status_t shadow_getspent(nss_backend_t *be,void *args)
+{
+  NSS_GETENT(LDAP_BE(be)->fp,NSLCD_ACTION_SHADOW_ALL,
+             READ_RESULT(LDAP_BE(be)->fp));
+}
+
+static nss_status_t shadow_endspent(nss_backend_t *be,void UNUSED(*args))
+{
+  NSS_ENDENT(LDAP_BE(be)->fp);
+}
+
+static nss_backend_op_t shadow_ops[]={
+  nss_ldap_destructor,
+  shadow_endspent,
+  shadow_setspent,
+  shadow_getspent,
+  shadow_getspnam
+};
+
+nss_backend_t *_nss_ldap_shadow_constr(const char UNUSED(*db_name),
+                  const char UNUSED(*src_name),const char UNUSED(*cfg_args))
+{
+  return nss_ldap_constructor(shadow_ops,sizeof(shadow_ops));
+}
+
+#endif /* NSS_FLAVOUR_SOLARIS */

Added: nss-pam-ldapd/nss/solnss.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ nss-pam-ldapd/nss/solnss.c  Thu Dec 30 14:13:26 2010        (r1354)
@@ -0,0 +1,49 @@
+/*
+   solnss.c - Solaris specific NSS interface functions
+
+   Copyright (C) 2010 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+#include "config.h"
+
+#include <errno.h>
+
+#include "prototypes.h"
+#include "common.h"
+#include "compat/attrs.h"
+
+nss_backend_t *nss_ldap_constructor(nss_backend_op_t *ops,size_t sizeofops)
+{
+  struct nss_ldap_backend *ldapbe;
+  ldapbe=(struct nss_ldap_backend *)malloc(sizeof(struct nss_ldap_backend));
+  if (ldapbe==NULL)
+    return NULL;
+  ldapbe->ops=ops;
+  ldapbe->n_ops=sizeofops/sizeof(nss_backend_op_t);
+  ldapbe->fp=NULL;
+  return (nss_backend_t *)ldapbe;
+}
+
+nss_status_t nss_ldap_destructor(nss_backend_t *be,void UNUSED(*args))
+{
+  struct nss_ldap_backend *ldapbe=(struct nss_ldap_backend *)be;
+  if (ldapbe->fp!=NULL)
+    (void)tio_close(ldapbe->fp);
+  free(ldapbe);
+  return NSS_STATUS_SUCCESS;
+}
--
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits