summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/Makefile.lint2
-rw-r--r--usr/src/cmd/initpkg/nscd.conf112
-rw-r--r--usr/src/cmd/ldap/Makefile.com8
-rw-r--r--usr/src/cmd/ldap/ns_ldap/idsconfig.sh379
-rw-r--r--usr/src/cmd/ldap/ns_ldap/ldapaddent.c137
-rw-r--r--usr/src/cmd/ldap/ns_ldap/ldapclient.c87
-rw-r--r--usr/src/cmd/ldap/ns_ldap/mapping.c73
-rw-r--r--usr/src/cmd/ldapcachemgr/Makefile9
-rw-r--r--usr/src/cmd/ldapcachemgr/cachemgr.c15
-rw-r--r--usr/src/cmd/ldapcachemgr/cachemgr_getldap.c212
-rw-r--r--usr/src/cmd/nscd/Makefile38
-rw-r--r--usr/src/cmd/nscd/cache.c2378
-rw-r--r--usr/src/cmd/nscd/cache.h372
-rw-r--r--usr/src/cmd/nscd/getauth.c (renamed from usr/src/cmd/nscd/attrstr.c)35
-rw-r--r--usr/src/cmd/nscd/getauuser.c46
-rw-r--r--usr/src/cmd/nscd/getbootp.c46
-rw-r--r--usr/src/cmd/nscd/getether.c97
-rw-r--r--usr/src/cmd/nscd/getexec.c564
-rw-r--r--usr/src/cmd/nscd/getgr.c607
-rw-r--r--usr/src/cmd/nscd/gethost.c694
-rw-r--r--usr/src/cmd/nscd/getnet.c120
-rw-r--r--usr/src/cmd/nscd/getnetmasks.c48
-rw-r--r--usr/src/cmd/nscd/getnode.c839
-rw-r--r--usr/src/cmd/nscd/getprinter.c47
-rw-r--r--usr/src/cmd/nscd/getprof.c490
-rw-r--r--usr/src/cmd/nscd/getproject.c80
-rw-r--r--usr/src/cmd/nscd/getproto.c54
-rw-r--r--usr/src/cmd/nscd/getpw.c669
-rw-r--r--usr/src/cmd/nscd/getrpc.c54
-rw-r--r--usr/src/cmd/nscd/getserv.c158
-rw-r--r--usr/src/cmd/nscd/gettnrhdb.c93
-rw-r--r--usr/src/cmd/nscd/gettnrhtp.c52
-rw-r--r--usr/src/cmd/nscd/getuser.c492
-rw-r--r--usr/src/cmd/nscd/hash.c346
-rw-r--r--usr/src/cmd/nscd/name-service-cache.xml19
-rw-r--r--usr/src/cmd/nscd/nscd.h127
-rw-r--r--usr/src/cmd/nscd/nscd_access.c588
-rw-r--r--usr/src/cmd/nscd/nscd_admin.c410
-rw-r--r--usr/src/cmd/nscd/nscd_admin.h81
-rw-r--r--usr/src/cmd/nscd/nscd_biggest.c92
-rw-r--r--usr/src/cmd/nscd/nscd_cfgdef.h1413
-rw-r--r--usr/src/cmd/nscd/nscd_cfgfile.c386
-rw-r--r--usr/src/cmd/nscd/nscd_common.h105
-rw-r--r--usr/src/cmd/nscd/nscd_config.c2923
-rw-r--r--usr/src/cmd/nscd/nscd_config.h653
-rw-r--r--usr/src/cmd/nscd/nscd_db.h253
-rw-r--r--usr/src/cmd/nscd/nscd_dbimpl.c617
-rw-r--r--usr/src/cmd/nscd/nscd_door.c353
-rw-r--r--usr/src/cmd/nscd/nscd_door.h175
-rw-r--r--usr/src/cmd/nscd/nscd_frontend.c1150
-rw-r--r--usr/src/cmd/nscd/nscd_frontend.h84
-rw-r--r--usr/src/cmd/nscd/nscd_getentctx.c661
-rw-r--r--usr/src/cmd/nscd/nscd_init.c241
-rw-r--r--usr/src/cmd/nscd/nscd_initf.c250
-rw-r--r--usr/src/cmd/nscd/nscd_intaddr.c248
-rw-r--r--usr/src/cmd/nscd/nscd_log.c427
-rw-r--r--usr/src/cmd/nscd/nscd_log.h96
-rw-r--r--usr/src/cmd/nscd/nscd_nswcfgst.c262
-rw-r--r--usr/src/cmd/nscd/nscd_nswconfig.c686
-rw-r--r--usr/src/cmd/nscd/nscd_nswparse.c379
-rw-r--r--usr/src/cmd/nscd/nscd_nswstate.c786
-rw-r--r--usr/src/cmd/nscd/nscd_parse.c402
-rw-r--r--usr/src/cmd/nscd/nscd_selfcred.c1589
-rw-r--r--usr/src/cmd/nscd/nscd_selfcred.h75
-rw-r--r--usr/src/cmd/nscd/nscd_seqnum.c59
-rw-r--r--usr/src/cmd/nscd/nscd_smfmonitor.c209
-rw-r--r--usr/src/cmd/nscd/nscd_switch.c1546
-rw-r--r--usr/src/cmd/nscd/nscd_switch.h399
-rw-r--r--usr/src/cmd/nscd/nscd_wait.c120
-rw-r--r--usr/src/cmd/nscd/req.flg31
-rw-r--r--usr/src/cmd/nscd/server.c1922
-rw-r--r--usr/src/cmd/nscd/svc-nscd10
-rw-r--r--usr/src/cmd/rpcsvc/nis/utils/nisaddent.c2
-rw-r--r--usr/src/head/nss_common.h171
-rw-r--r--usr/src/head/nss_dbdefs.h329
-rw-r--r--usr/src/head/nss_netdir.h7
-rw-r--r--usr/src/head/nsswitch.h12
-rw-r--r--usr/src/lib/libc/inc/nsswitch_priv.h1
-rw-r--r--usr/src/lib/libc/inc/tsd.h16
-rw-r--r--usr/src/lib/libc/port/gen/getgrnam_r.c272
-rw-r--r--usr/src/lib/libc/port/gen/getnetgrent.c19
-rw-r--r--usr/src/lib/libc/port/gen/getpwnam.c7
-rw-r--r--usr/src/lib/libc/port/gen/getpwnam_r.c184
-rw-r--r--usr/src/lib/libc/port/gen/getspent_r.c21
-rw-r--r--usr/src/lib/libc/port/gen/getxby_door.c610
-rw-r--r--usr/src/lib/libc/port/gen/getxby_door.h289
-rw-r--r--usr/src/lib/libc/port/gen/nss_common.c1249
-rw-r--r--usr/src/lib/libc/port/gen/nss_dbdefs.c1123
-rw-r--r--usr/src/lib/libc/port/gen/nss_deffinder.c17
-rw-r--r--usr/src/lib/libc/port/mapfile-vers10
-rw-r--r--usr/src/lib/libnsl/common/llib-lnsl10
-rw-r--r--usr/src/lib/libnsl/key/publickey.c19
-rw-r--r--usr/src/lib/libnsl/nss/getauthattr.c17
-rw-r--r--usr/src/lib/libnsl/nss/getauuser.c17
-rw-r--r--usr/src/lib/libnsl/nss/getexecattr.c29
-rw-r--r--usr/src/lib/libnsl/nss/gethostby_door.c275
-rw-r--r--usr/src/lib/libnsl/nss/gethostbyname_r.c10
-rw-r--r--usr/src/lib/libnsl/nss/gethostent.c5
-rw-r--r--usr/src/lib/libnsl/nss/getipnodeby_door.c288
-rw-r--r--usr/src/lib/libnsl/nss/getprofattr.c16
-rw-r--r--usr/src/lib/libnsl/nss/getrpcent_r.c9
-rw-r--r--usr/src/lib/libnsl/nss/getuserattr.c17
-rw-r--r--usr/src/lib/libnsl/nss/netdir_inet.c7
-rw-r--r--usr/src/lib/libsecdb/common/getexecattr.c137
-rw-r--r--usr/src/lib/libsecdb/common/getprofattr.c112
-rw-r--r--usr/src/lib/libsecdb/common/getuserattr.c109
-rw-r--r--usr/src/lib/libsldap/Makefile.com12
-rw-r--r--usr/src/lib/libsldap/common/llib-lsldap53
-rw-r--r--usr/src/lib/libsldap/common/mapfile-vers6
-rw-r--r--usr/src/lib/libsldap/common/ns_cache_door.h9
-rw-r--r--usr/src/lib/libsldap/common/ns_common.c16
-rw-r--r--usr/src/lib/libsldap/common/ns_config.c49
-rw-r--r--usr/src/lib/libsldap/common/ns_connect.c935
-rw-r--r--usr/src/lib/libsldap/common/ns_init.c21
-rw-r--r--usr/src/lib/libsldap/common/ns_internal.h65
-rw-r--r--usr/src/lib/libsldap/common/ns_reads.c28
-rw-r--r--usr/src/lib/libsldap/common/ns_sasl.c580
-rw-r--r--usr/src/lib/libsldap/common/ns_sldap.h29
-rw-r--r--usr/src/lib/libsldap/common/ns_writes.c6
-rw-r--r--usr/src/lib/libsldap/req.flg1
-rw-r--r--usr/src/lib/libsocket/common/mapfile-vers9
-rw-r--r--usr/src/lib/libsocket/inet/ether_addr.c11
-rw-r--r--usr/src/lib/libsocket/inet/getnetent_r.c17
-rw-r--r--usr/src/lib/libsocket/inet/getprotoent_r.c18
-rw-r--r--usr/src/lib/libsocket/inet/getservent_r.c10
-rw-r--r--usr/src/lib/libsocket/inet/netmasks.c30
-rw-r--r--usr/src/lib/nsswitch/compat/common/compat_common.c352
-rw-r--r--usr/src/lib/nsswitch/compat/common/compat_common.h47
-rw-r--r--usr/src/lib/nsswitch/compat/common/getauuser.c12
-rw-r--r--usr/src/lib/nsswitch/compat/common/getgrent.c36
-rw-r--r--usr/src/lib/nsswitch/compat/common/getpwent.c77
-rw-r--r--usr/src/lib/nsswitch/compat/common/getspent.c56
-rw-r--r--usr/src/lib/nsswitch/compat/common/getuserattr.c12
-rw-r--r--usr/src/lib/nsswitch/dns/Makefile.com9
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_common.c389
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_common.h20
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_mt.c12
-rw-r--r--usr/src/lib/nsswitch/dns/common/gethostent.c76
-rw-r--r--usr/src/lib/nsswitch/dns/common/gethostent6.c63
-rw-r--r--usr/src/lib/nsswitch/dns/common/mapfile-vers9
-rw-r--r--usr/src/lib/nsswitch/files/Makefile.com4
-rw-r--r--usr/src/lib/nsswitch/files/common/bootparams_getbyname.c18
-rw-r--r--usr/src/lib/nsswitch/files/common/ether_addr.c89
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.c142
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.h10
-rw-r--r--usr/src/lib/nsswitch/files/common/getauthattr.c24
-rw-r--r--usr/src/lib/nsswitch/files/common/getauuser.c24
-rw-r--r--usr/src/lib/nsswitch/files/common/getexecattr.c90
-rw-r--r--usr/src/lib/nsswitch/files/common/getgrent.c123
-rw-r--r--usr/src/lib/nsswitch/files/common/gethostent.c501
-rw-r--r--usr/src/lib/nsswitch/files/common/gethostent6.c21
-rw-r--r--usr/src/lib/nsswitch/files/common/getnetent.c78
-rw-r--r--usr/src/lib/nsswitch/files/common/getprinter.c145
-rw-r--r--usr/src/lib/nsswitch/files/common/getprofattr.c24
-rw-r--r--usr/src/lib/nsswitch/files/common/getprojent.c95
-rw-r--r--usr/src/lib/nsswitch/files/common/getprotoent.c59
-rw-r--r--usr/src/lib/nsswitch/files/common/getpwnam.c118
-rw-r--r--usr/src/lib/nsswitch/files/common/getrpcent.c61
-rw-r--r--usr/src/lib/nsswitch/files/common/getservent.c146
-rw-r--r--usr/src/lib/nsswitch/files/common/getspent.c29
-rw-r--r--usr/src/lib/nsswitch/files/common/getuserattr.c24
-rw-r--r--usr/src/lib/nsswitch/files/common/netmasks.c89
-rw-r--r--usr/src/lib/nsswitch/files/common/tsol_getrhent.c87
-rw-r--r--usr/src/lib/nsswitch/files/common/tsol_gettpent.c21
-rw-r--r--usr/src/lib/nsswitch/ldap/Makefile.com2
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getauthattr.c249
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getauuser.c167
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getbootparams.c134
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getether.c161
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getexecattr.c189
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getgrent.c269
-rw-r--r--usr/src/lib/nsswitch/ldap/common/gethostent.c418
-rw-r--r--usr/src/lib/nsswitch/ldap/common/gethostent6.c279
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getkeyent.c137
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetent.c248
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetgrent.c2
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetmasks.c107
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprinter.c240
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprofattr.c225
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprojent.c283
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprotoent.c300
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getpwnam.c253
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getrpcent.c189
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getservent.c311
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getspent.c255
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getuserattr.c219
-rw-r--r--usr/src/lib/nsswitch/ldap/common/ldap_common.c149
-rw-r--r--usr/src/lib/nsswitch/ldap/common/ldap_common.h27
-rw-r--r--usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c162
-rw-r--r--usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c134
-rw-r--r--usr/src/lib/nsswitch/nis/Makefile.com10
-rw-r--r--usr/src/lib/nsswitch/nis/common/ether_addr.c19
-rw-r--r--usr/src/lib/nsswitch/nis/common/getauthattr.c10
-rw-r--r--usr/src/lib/nsswitch/nis/common/getauuser.c10
-rw-r--r--usr/src/lib/nsswitch/nis/common/getexecattr.c71
-rw-r--r--usr/src/lib/nsswitch/nis/common/getgrent.c13
-rw-r--r--usr/src/lib/nsswitch/nis/common/gethostent.c15
-rw-r--r--usr/src/lib/nsswitch/nis/common/gethostent6.c9
-rw-r--r--usr/src/lib/nsswitch/nis/common/getnetgrent.c35
-rw-r--r--usr/src/lib/nsswitch/nis/common/getprinter.c9
-rw-r--r--usr/src/lib/nsswitch/nis/common/getprofattr.c10
-rw-r--r--usr/src/lib/nsswitch/nis/common/getprojent.c11
-rw-r--r--usr/src/lib/nsswitch/nis/common/getpwnam.c15
-rw-r--r--usr/src/lib/nsswitch/nis/common/getrpcent.c50
-rw-r--r--usr/src/lib/nsswitch/nis/common/getservent.c187
-rw-r--r--usr/src/lib/nsswitch/nis/common/getspent.c119
-rw-r--r--usr/src/lib/nsswitch/nis/common/getuserattr.c10
-rw-r--r--usr/src/lib/nsswitch/nis/common/nis_common.c91
-rw-r--r--usr/src/lib/nsswitch/nis/common/nis_common.h10
-rw-r--r--usr/src/lib/nsswitch/nisplus/Makefile.com10
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/bootparams_getbyname.c73
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/ether_addr.c104
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getauthattr.c159
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getauuser.c98
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getexecattr.c278
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getgrent.c152
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/gethostent.c185
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/gethostent6.c89
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getnetent.c135
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getnetgrent.c51
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getprinter.c88
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getprofattr.c135
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getprotoent.c125
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getpwnam.c201
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getrpcent.c125
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getservent.c180
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getspent.c208
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/getuserattr.c138
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/netmasks.c66
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/nisplus_common.c426
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/nisplus_common.h111
-rw-r--r--usr/src/lib/nsswitch/nisplus/common/nisplus_tables.h37
-rw-r--r--usr/src/lib/nsswitch/user/Makefile.com2
-rw-r--r--usr/src/lib/nsswitch/user/common/getprinter.c15
-rw-r--r--usr/src/lib/nsswitch/user/common/user_common.c9
-rw-r--r--usr/src/lib/print/libprint/common/nss_printer.c2
236 files changed, 33883 insertions, 14925 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 6b744020b8..39e8a32294 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -194,6 +194,7 @@ COMMON_SUBDIRS = \
cmd/nispasswd \
cmd/nl \
cmd/nohup \
+ cmd/nscd \
cmd/pagesize \
cmd/passwd \
cmd/pathchk \
@@ -377,6 +378,7 @@ COMMON_SUBDIRS = \
lib/mpss \
lib/nametoaddr \
lib/ncad_addr \
+ lib/nsswitch \
lib/pam_modules \
lib/passwdutil \
lib/pkcs11 \
diff --git a/usr/src/cmd/initpkg/nscd.conf b/usr/src/cmd/initpkg/nscd.conf
index 9152f40cb4..a2a06950ce 100644
--- a/usr/src/cmd/initpkg/nscd.conf
+++ b/usr/src/cmd/initpkg/nscd.conf
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,67 +19,120 @@
# CDDL HEADER END
#
#
-# Copyright (c) 1994-2001 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
#
#
-# Currently supported cache names: passwd, group, hosts, ipnodes
-# exec_attr, prof_attr, user_attr
+# Currently supported cache names:
+# audit_user, auth_attr, bootparams, ethers
+# exec_attr, group, hosts, ipnodes, netmasks
+# networks, passwd, printers, prof_attr, project
+# protocols, rpc, services, tnrhdb, tnrhtp, user_attr
#
-
# logfile /var/adm/nscd.log
# enable-cache hosts no
debug-level 0
- positive-time-to-live passwd 600
- negative-time-to-live passwd 5
- suggested-size passwd 211
- keep-hot-count passwd 20
- old-data-ok passwd no
- check-files passwd yes
+ positive-time-to-live audit_user 3600
+ negative-time-to-live audit_user 5
+ keep-hot-count audit_user 20
+ check-files audit_user yes
+
+ positive-time-to-live auth_attr 3600
+ negative-time-to-live auth_attr 5
+ keep-hot-count auth_attr 20
+ check-files auth_attr yes
+
+ positive-time-to-live bootparams 3600
+ negative-time-to-live bootparams 5
+ keep-hot-count bootparams 20
+ check-files bootparams yes
+
+ positive-time-to-live ethers 3600
+ negative-time-to-live ethers 5
+ keep-hot-count ethers 20
+ check-files ethers yes
+
+ positive-time-to-live exec_attr 3600
+ negative-time-to-live exec_attr 300
+ keep-hot-count exec_attr 20
+ check-files exec_attr yes
positive-time-to-live group 3600
negative-time-to-live group 5
- suggested-size group 211
keep-hot-count group 20
- old-data-ok group no
check-files group yes
positive-time-to-live hosts 3600
negative-time-to-live hosts 5
- suggested-size hosts 211
keep-hot-count hosts 20
- old-data-ok hosts no
check-files hosts yes
positive-time-to-live ipnodes 3600
negative-time-to-live ipnodes 5
- suggested-size ipnodes 211
keep-hot-count ipnodes 20
- old-data-ok ipnodes no
check-files ipnodes yes
- positive-time-to-live exec_attr 3600
- negative-time-to-live exec_attr 300
- suggested-size exec_attr 211
- keep-hot-count exec_attr 20
- old-data-ok exec_attr no
- check-files exec_attr yes
+ positive-time-to-live netmasks 3600
+ negative-time-to-live netmasks 5
+ keep-hot-count netmasks 20
+ check-files netmasks yes
+
+ positive-time-to-live networks 3600
+ negative-time-to-live networks 5
+ keep-hot-count networks 20
+ check-files networks yes
+
+ positive-time-to-live passwd 600
+ negative-time-to-live passwd 5
+ keep-hot-count passwd 20
+ check-files passwd yes
+
+ positive-time-to-live printers 3600
+ negative-time-to-live printers 5
+ keep-hot-count printers 20
+ check-files printers yes
positive-time-to-live prof_attr 3600
negative-time-to-live prof_attr 5
- suggested-size prof_attr 211
keep-hot-count prof_attr 20
- old-data-ok prof_attr no
check-files prof_attr yes
+ positive-time-to-live project 3600
+ negative-time-to-live project 5
+ keep-hot-count project 20
+ check-files project yes
+
+ positive-time-to-live protocols 3600
+ negative-time-to-live protocols 5
+ keep-hot-count protocols 20
+ check-files protocols yes
+
+ positive-time-to-live rpc 3600
+ negative-time-to-live rpc 5
+ keep-hot-count rpc 20
+ check-files rpc yes
+
+ positive-time-to-live services 3600
+ negative-time-to-live services 5
+ keep-hot-count services 20
+ check-files services yes
+
+ positive-time-to-live tnrhdb 3600
+ negative-time-to-live tnrhdb 5
+ keep-hot-count tnrhdb 20
+ check-files tnrhdb yes
+
+ positive-time-to-live tnrhtp 3600
+ negative-time-to-live tnrhtp 5
+ keep-hot-count tnrhtp 20
+ check-files tnrhtp yes
+
positive-time-to-live user_attr 3600
negative-time-to-live user_attr 5
- suggested-size user_attr 211
keep-hot-count user_attr 20
- old-data-ok user_attr no
check-files user_attr yes
diff --git a/usr/src/cmd/ldap/Makefile.com b/usr/src/cmd/ldap/Makefile.com
index d65d341a22..f6b9609477 100644
--- a/usr/src/cmd/ldap/Makefile.com
+++ b/usr/src/cmd/ldap/Makefile.com
@@ -95,9 +95,9 @@ lint:= TARGET= lint
# C Pre-Processor flags used by C, CC & lint
CPPFLAGS += -DSUN -DSVR4 -DSOLARIS_LDAP_CMD \
- -I ../../../lib/libldap5/include/ldap \
- -I ../../../lib/libsldap/common \
- -I ../../../lib/libnsl/include/rpcsvc \
+ -I $(SRC)/lib/libldap5/include/ldap \
+ -I $(SRC)/lib/libsldap/common \
+ -I $(SRC)/lib/libnsl/include/rpcsvc \
-DNO_LIBLCACHE -DLDAP_REFERRALS -DNET_SSL -DLDAPSSLIO \
-DHAVE_SASL_OPTIONS -DSOLARIS_LDAP_CMD
LDLIBS += $(COMPLIB)
@@ -177,7 +177,7 @@ lintns_ldaplist:
lintns_ldapaddent:
$(LINT.c) $(LDAPADDENTSRCS:%=../ns_ldap/%) $(LDLIBS) -lsldap -lnsl \
- >> $(LINTOUT) 2>&1
+ -lsecdb >> $(LINTOUT) 2>&1
lintns_ldapclient:
$(LINT.c) $(LDAPCLIENTSRCS:%=../ns_ldap/%) $(LDLIBS) -lsldap -lscf \
diff --git a/usr/src/cmd/ldap/ns_ldap/idsconfig.sh b/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
index 3e81b6d6bb..d1d38b3dca 100644
--- a/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
+++ b/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
@@ -22,7 +22,7 @@
# CDDL HEADER END
#
#
-# idsconfig -- script to setup iDS 5.x for Native LDAP II.
+# idsconfig -- script to setup iDS 5.x/6.x for Native LDAP II.
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
@@ -69,6 +69,9 @@ The following are the supported credential levels:
1 anonymous
2 proxy
3 proxy anonymous
+ 4 self
+ 5 self proxy
+ 6 self proxy anonymous
EOF
;;
auth_method_menu) cat <<EOF
@@ -78,6 +81,7 @@ The following are the supported Authentication Methods:
3 sasl/DIGEST-MD5
4 tls:simple
5 tls:sasl/DIGEST-MD5
+ 6 sasl/GSSAPI
EOF
;;
srvauth_method_menu) cat <<EOF
@@ -86,6 +90,7 @@ The following are the supported Authentication Methods:
2 sasl/DIGEST-MD5
3 tls:simple
4 tls:sasl/DIGEST-MD5
+ 5 sasl/GSSAPI
EOF
;;
prompt_ssd_menu) cat <<EOF
@@ -931,6 +936,7 @@ init()
DEBUG=0 # Set Debug OFF
BACKUP=no_ldap # backup suffix
HOST="" # NULL or <hostname>
+ NAWK="/usr/bin/nawk"
DOM="" # Set to NULL
# If DNS domain (resolv.conf) exists use that, otherwise use domainname.
@@ -1015,6 +1021,11 @@ init()
# Set the SSD file name after setting TMPDIR.
SSD_FILE=${TMPDIR}/ssd_list
+
+ # GSSAPI setup
+ LDAP_KRB_REALM=""
+ LDAP_GSSAPI_PROFILE=""
+ SCHEMA_UPDATED=0
export DEBUG VERB ECHO EVAL EGREP GREP STEP TMPDIR
export IDS_SERVER IDS_PORT LDAP_ROOTDN LDAP_ROOTPWD LDAP_SERVER_LIST
@@ -1027,7 +1038,7 @@ init()
export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
export LDAP_SERV_SRCH_DES SSD_FILE
- export GEN_CMD
+ export GEN_CMD LDAP_KRB_REALM LDAP_GSSAPI_PROFILE SCHEMA_UPDATED
}
@@ -1127,8 +1138,8 @@ get_ids_server()
while :
do
# Prompt for server name.
- get_ans "Enter the iPlanet Directory Server's (iDS) hostname to setup:" "$IDS_SERVER"
- IDS_SERVER=$ANS
+ get_ans "Enter the JES Directory Server's hostname to setup:" "$IDS_SERVER"
+ IDS_SERVER="$ANS"
# Ping server to see if live. If valid break out of loop.
ping $IDS_SERVER > /dev/null 2>&1
@@ -1159,7 +1170,6 @@ get_ids_port()
# Enter port number.
get_number "Enter the port number for iDS (h=help):" "$IDS_PORT" "port_help"
IDS_PORT=$ANS
-
# Do a simple search to check hostname and port number.
# If search returns SUCCESS, break out, host and port must
# be valid.
@@ -1196,8 +1206,8 @@ chk_ids_version()
IDS_VER=`cat ${TMPDIR}/checkDSver`
IDS_MAJVER=`${ECHO} ${IDS_VER} | cut -f1 -d.`
IDS_MINVER=`${ECHO} ${IDS_VER} | cut -f2 -d.`
- if [ "${IDS_MAJVER}" != "5" ]; then
- ${ECHO} "ERROR: $PROG only works with iDS version 5.x, not ${IDS_VER}."
+ if [ "${IDS_MAJVER}" != "5" ] && [ "${IDS_MAJVER}" != "6" ]; then
+ ${ECHO} "ERROR: $PROG only works with JES DS version 5.x and 6.x, not ${IDS_VER}."
exit 1
fi
if [ $DEBUG -eq 1 ]; then
@@ -1336,7 +1346,326 @@ get_basedn()
done
}
+get_krb_realm() {
+
+ # To upper cases
+ LDAP_KRB_REALM=`${ECHO} ${LDAP_DOMAIN} | ${NAWK} '{ print toupper($0) }'`
+ get_ans_req "Enter Kerberos Realm:" "$LDAP_KRB_REALM"
+ # To upper cases
+ LDAP_KRB_REALM=`${ECHO} ${ANS} | ${NAWK} '{ print toupper($0) }'`
+}
+
+# $1: DN
+# $2: ldif file
+add_entry_by_DN() {
+
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${1}\" -s base \"objectclass=*\" ${VERB}"
+ if [ $? -eq 0 ]; then
+ ${ECHO} " ${1} already exists"
+ return 0
+ else
+ ${EVAL} "${LDAPADD} ${LDAP_ARGS} -f ${2} ${VERB}"
+ if [ $? -eq 0 ]; then
+ ${ECHO} " ${1} is added"
+ return 0
+ else
+ ${ECHO} " ERROR: failed to add ${1}"
+ return 1
+ fi
+ fi
+
+}
+#
+# Kerberos princiapl to DN mapping rules
+#
+# Add rules for host credentails and user credentials
+#
+add_id_mapping_rules() {
+
+ ${ECHO} " Adding Kerberos principal to DN mapping rules..."
+
+ _C_DN="cn=GSSAPI,cn=identity mapping,cn=config"
+ ( cat << EOF
+dn: cn=GSSAPI,cn=identity mapping,cn=config
+objectClass: top
+objectClass: nsContainer
+cn: GSSAPI
+EOF
+) > ${TMPDIR}/GSSAPI_container.ldif
+
+ add_entry_by_DN "${_C_DN}" "${TMPDIR}/GSSAPI_container.ldif"
+ if [ $? -ne 0 ];
+ then
+ ${RM} ${TMPDIR}/GSSAPI_container.ldif
+ return
+ fi
+
+ _H_CN="host_auth_${LDAP_KRB_REALM}"
+ _H_DN="cn=${_H_CN}, ${_C_DN}"
+ ( cat << EOF
+dn: ${_H_DN}
+objectClass: top
+objectClass: nsContainer
+objectClass: dsIdentityMapping
+objectClass: dsPatternMatching
+cn: ${_H_CN}
+dsMatching-pattern: \${Principal}
+dsMatching-regexp: host\/(.*).${LDAP_DOMAIN}@${LDAP_KRB_REALM}
+dsSearchBaseDN: ou=hosts,${LDAP_BASEDN}
+dsSearchFilter: (&(objectClass=ipHost)(cn=\$1))
+dsSearchScope: one
+
+EOF
+) > ${TMPDIR}/${_H_CN}.ldif
+
+ add_entry_by_DN "${_H_DN}" "${TMPDIR}/${_H_CN}.ldif"
+
+ _U_CN="user_auth_${LDAP_KRB_REALM}"
+ _U_DN="cn=${_U_CN}, ${_C_DN}"
+ ( cat << EOF
+dn: ${_U_DN}
+objectClass: top
+objectClass: nsContainer
+objectClass: dsIdentityMapping
+objectClass: dsPatternMatching
+cn: ${_U_CN}
+dsMatching-pattern: \${Principal}
+dsMatching-regexp: (.*)@${LDAP_KRB_REALM}
+dsMappedDN: uid=\$1,ou=People,${LDAP_BASEDN}
+
+EOF
+) > ${TMPDIR}/${_U_CN}.ldif
+
+ add_entry_by_DN "${_U_DN}" "${TMPDIR}/${_U_CN}.ldif"
+
+}
+
+
+#
+# Modify ACL to allow root to read all the password and only self can read
+# its own password when sasl/GSSAPI bind is used
#
+modify_userpassword_acl_for_gssapi() {
+
+ _P_DN="ou=People,${LDAP_BASEDN}"
+ _H_DN="ou=Hosts,${LDAP_BASEDN}"
+ _P_ACI="self-read-pwd"
+
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${_P_DN}\" -s base \"objectclass=*\" > /dev/null 2>&1"
+ if [ $? -ne 0 ]; then
+ ${ECHO} " ${_P_DN} does not exist"
+ # Not Found. Create a new entry
+ ( cat << EOF
+dn: ${_P_DN}
+ou: People
+objectClass: top
+objectClass: organizationalUnit
+EOF
+) > ${TMPDIR}/gssapi_people.ldif
+
+ add_entry_by_DN "${_P_DN}" "${TMPDIR}/gssapi_people.ldif"
+ else
+ ${ECHO} " ${_P_DN} already exists"
+ fi
+
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${_P_DN}\" -s base \"objectclass=*\" aci > ${TMPDIR}/chk_gssapi_aci 2>&1"
+
+ if [ $? -eq 0 ]; then
+ ${EVAL} "${GREP} ${_P_ACI} ${TMPDIR}/chk_gssapi_aci > /dev/null 2>&1"
+ if [ $? -eq 0 ]; then
+ ${ECHO} " userpassword ACL ${_P_ACI} already exists."
+ return
+ else
+ ${ECHO} " userpassword ACL ${_P_ACI} not found. Create a new one."
+ fi
+ else
+ ${ECHO} " Error searching aci for ${_P_DN}"
+ cat ${TMPDIR}/chk_gssapi_aci
+ cleanup
+ exit 1
+ fi
+ ( cat << EOF
+dn: ${_P_DN}
+changetype: modify
+add: aci
+aci: (targetattr="userPassword")(version 3.0; acl self-read-pwd; allow (read,search) userdn="ldap:///self" and authmethod="sasl GSSAPI";)
+-
+add: aci
+aci: (targetattr="userPassword")(version 3.0; acl host-read-pwd; allow (read,search) userdn="ldap:///cn=*+ipHostNumber=*,ou=Hosts,${LDAP_BASEDN}" and authmethod="sasl GSSAPI";)
+EOF
+) > ${TMPDIR}/user_gssapi.ldif
+ LDAP_TYPE_OR_VALUE_EXISTS=20
+ ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/user_gssapi.ldif ${VERB}"
+
+ case $? in
+ 0)
+ ${ECHO} " ${_P_DN} uaserpassword ACL is updated."
+ ;;
+ 20)
+ ${ECHO} " ${_P_DN} uaserpassword ACL already exists."
+ ;;
+ *)
+ ${ECHO} " ERROR: update of userpassword ACL for ${_P_DN} failed!"
+ cleanup
+ exit 1
+ ;;
+ esac
+}
+#
+# $1: objectclass or attributetyp
+# $2: name
+search_update_schema() {
+
+ ATTR="${1}es"
+
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b cn=schema -s base \"objectclass=*\" ${ATTR} | ${GREP} -i \"${2}\" ${VERB}"
+ if [ $? -ne 0 ]; then
+ ${ECHO} "${1} ${2} does not exist."
+ update_schema_attr
+ update_schema_obj
+ SCHEMA_UPDATED=1
+ else
+ ${ECHO} "${1} ${2} already exists. Schema has been updated"
+ fi
+}
+
+#
+# $1: 1 - interactive, 0 - no
+#
+create_gssapi_profile() {
+
+
+ if [ ${1} -eq 1 ]; then
+ echo
+ echo "You can create a sasl/GSSAPI enabled profile with default values now."
+ get_confirm "Do you want to create a sasl/GSSAPI default profile ?" "n"
+
+ if [ $? -eq 0 ]; then
+ return
+ fi
+ fi
+
+ # Add profile container if it does not exist
+ eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" > /dev/null 2>&1"
+ if [ $? -ne 0 ]; then
+ ( cat << EOF
+dn: ou=profile,${LDAP_BASEDN}
+ou: profile
+objectClass: top
+objectClass: organizationalUnit
+EOF
+) > ${TMPDIR}/profile_people.ldif
+
+ add_entry_by_DN "ou=profile,${LDAP_BASEDN}" "${TMPDIR}/profile_people.ldif"
+
+ fi
+
+ search_update_schema "objectclass" "DUAConfigProfile"
+
+ _P_NAME="gssapi_${LDAP_KRB_REALM}"
+ if [ ${1} -eq 1 ]; then
+ _P_TMP=${LDAP_PROFILE_NAME}
+ LDAP_PROFILE_NAME=${_P_NAME}
+ get_profile_name
+ LDAP_GSSAPI_PROFILE=${LDAP_PROFILE_NAME}
+ LDAP_PROFILE_NAME=${_P_TMP}
+ fi
+
+ _P_DN="cn=${LDAP_GSSAPI_PROFILE},ou=profile,${LDAP_BASEDN}"
+ if [ ${DEL_OLD_PROFILE} -eq 1 ]; then
+ DEL_OLD_PROFILE=0
+ ${EVAL} "${LDAPDELETE} ${LDAP_ARGS} ${_P_DN} ${VERB}"
+ fi
+
+ _SVR=`getent hosts ${IDS_SERVER} | ${NAWK} '{ print $1 }'`
+ if [ ${IDS_PORT} -ne 389 ]; then
+ _SVR="${_SVR}:${IDS_PORT}"
+ fi
+
+ (cat << EOF
+dn: ${_P_DN}
+objectClass: top
+objectClass: DUAConfigProfile
+defaultServerList: ${_SVR}
+defaultSearchBase: ${LDAP_BASEDN}
+authenticationMethod: sasl/GSSAPI
+followReferrals: ${LDAP_FOLLOWREF}
+defaultSearchScope: ${LDAP_SEARCH_SCOPE}
+searchTimeLimit: ${LDAP_SEARCH_TIME_LIMIT}
+profileTTL: ${LDAP_PROFILE_TTL}
+cn: ${LDAP_GSSAPI_PROFILE}
+credentialLevel: self
+bindTimeLimit: ${LDAP_BIND_LIMIT}
+EOF
+) > ${TMPDIR}/gssapi_profile.ldif
+
+ add_entry_by_DN "${_P_DN}" "${TMPDIR}/gssapi_profile.ldif"
+
+}
+#
+# Set up GSSAPI if necessary
+#
+gssapi_setup() {
+
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" supportedSASLMechanisms | ${GREP} GSSAPI ${VERB}"
+ if [ $? -ne 0 ]; then
+ ${ECHO} " sasl/GSSAPI is not supported by this LDAP server"
+ return
+ fi
+
+ get_confirm "GSSAPI is supported. Do you want to set up gssapi:(y/n)" "n"
+ if [ $? -eq 0 ]; then
+ ${ECHO}
+ ${ECHO} "GSSAPI is not set up."
+ ${ECHO} "sasl/GSSAPI bind may not workif it's not set up before."
+ else
+ get_krb_realm
+ add_id_mapping_rules
+ modify_userpassword_acl_for_gssapi
+ create_gssapi_profile 1
+ ${ECHO}
+ ${ECHO} "GSSAPI setup is done."
+ fi
+
+ cat << EOF
+
+You can continue to create a profile and
+configure the LDAP server.
+Or you can stop now.
+
+EOF
+ get_confirm "Do you want to stop:(y/n)" "n"
+ if [ $? -eq 1 ]; then
+ cleanup
+ exit
+ fi
+
+}
+gssapi_setup_auto() {
+ ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" supportedSASLMechanisms | ${GREP} GSSAPI ${VERB}"
+ if [ $? -ne 0 ]; then
+ ${ECHO}
+ ${ECHO} "sasl/GSSAPI is not supported by this LDAP server"
+ ${ECHO}
+ return
+ fi
+ if [ -z "${LDAP_KRB_REALM}" ]; then
+ ${ECHO}
+ ${ECHO} "LDAP_KRB_REALM is not set. Skip gssapi setup."
+ ${ECHO} "sasl/GSSAPI bind won't work properly."
+ ${ECHO}
+ return
+ fi
+ if [ -z "${LDAP_GSSAPI_PROFILE}" ]; then
+ ${ECHO}
+ ${ECHO} "LDAP_GSSAPI_PROFILE is not set. Default is gssapi_${LDAP_KRB_REALM}"
+ ${ECHO}
+ LDAP_GSSAPI_PROFILE="gssapi_${LDAP_KRB_REALM}"
+ fi
+ add_id_mapping_rules
+ modify_userpassword_acl_for_gssapi
+ create_gssapi_profile 0
+}
# get_profile_name(): Enter the profile name.
#
get_profile_name()
@@ -1470,8 +1799,17 @@ get_cred_level()
return 2 ;;
3) LDAP_CRED_LEVEL="proxy anonymous"
return 3 ;;
+ 4) LDAP_CRED_LEVEL="self"
+ SELF_GSSAPI=1
+ return 4 ;;
+ 5) LDAP_CRED_LEVEL="self proxy"
+ SELF_GSSAPI=1
+ return 5 ;;
+ 6) LDAP_CRED_LEVEL="self proxy anonymous"
+ SELF_GSSAPI=1
+ return 6 ;;
h) display_msg cred_lvl_help ;;
- *) ${ECHO} "Please enter 1, 2 or 3." ;;
+ *) ${ECHO} "Please enter 1, 2, 3, 4, 5 or 6." ;;
esac
done
}
@@ -1506,10 +1844,12 @@ srvauth_menu_handler()
break ;;
4) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
break ;;
+ 5) _AUTHMETHOD="sasl/GSSAPI"
+ break ;;
0) _AUTHMETHOD=""
_FIRST=1
break ;;
- *) ${ECHO} "Please enter 1-4 or 0 to reset." ;;
+ *) ${ECHO} "Please enter 1-5 or 0 to reset." ;;
esac
done
}
@@ -1546,11 +1886,13 @@ auth_menu_handler()
break ;;
5) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
break ;;
+ 6) _AUTHMETHOD="sasl/GSSAPI"
+ break ;;
0) _AUTHMETHOD=""
_FIRST=1
break ;;
h) display_msg auth_help ;;
- *) ${ECHO} "Please enter 1-5, 0=reset, or h=help." ;;
+ *) ${ECHO} "Please enter 1-6, 0=reset, or h=help." ;;
esac
done
}
@@ -2109,6 +2451,8 @@ prompt_config_info()
get_basedn
+ gssapi_setup
+
get_profile_name
get_srv_list
get_pref_srv
@@ -2153,6 +2497,7 @@ prompt_config_info()
NEED_SRVAUTH_CMD=$?
[ $NEED_SRVAUTH_CMD -eq 1 ] && get_srv_authMethod_cmd
fi
+
# Get Timeouts
get_srch_time
@@ -2298,6 +2643,8 @@ LDAP_ROOTDN="$LDAP_ROOTDN"
LDAP_ROOTPWD=$LDAP_ROOTPWD
LDAP_DOMAIN="$LDAP_DOMAIN"
LDAP_SUFFIX="$LDAP_SUFFIX"
+LDAP_KRB_REALM="$LDAP_KRB_REALM"
+LDAP_GSSAPI_PROFILE="$LDAP_GSSAPI_PROFILE"
# Internal program variables that need to be set.
NEED_PROXY=$NEED_PROXY
@@ -2338,7 +2685,7 @@ export LDAP_AUTHMETHOD LDAP_FOLLOWREF LDAP_SEARCH_SCOPE LDAP_SEARCH_TIME_LIMIT
export LDAP_PREF_SRVLIST LDAP_PROFILE_TTL LDAP_CRED_LEVEL LDAP_BIND_LIMIT
export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
-export LDAP_SERV_SRCH_DES SSD_FILE
+export LDAP_SERV_SRCH_DES SSD_FILE LDAP_KRB_REALM LDAP_GSSAPI_PROFILE
# Service Search Descriptors start here if present:
EOF
@@ -3103,6 +3450,9 @@ add_eq_indexes()
# Set eq indexes to add.
_INDEXES="uidNumber ipNetworkNumber gidnumber oncrpcnumber automountKey"
+ if [ -z "${IDS_DATABASE}" ]; then
+ get_backend
+ fi
# Set _EXT to use as shortcut.
_EXT="cn=index,cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
@@ -4312,6 +4662,7 @@ then
INTERACTIVE=0 # Turns off prompts that occur later.
validate_info # Validate basic info in file.
chk_ids_version # Check iDS version for compatibility.
+ gssapi_setup_auto
else
# Display BACKUP warning to user.
display_msg backup_server
@@ -4341,8 +4692,10 @@ if [ "$NEED_CRYPT" = "TRUE" ]; then
fi
# Update the schema (Attributes, Objectclass Definitions)
-update_schema_attr
-update_schema_obj
+if [ ${SCHEMA_UPDATED} -eq 0 ]; then
+ update_schema_attr
+ update_schema_obj
+fi
# Add suffix together with its root entry (if needed)
add_suffix ||
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
index e05d591da1..641092fea7 100644
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
@@ -80,9 +80,6 @@ extern int optind;
extern char *optarg;
extern char *__nis_quote_key(const char *, char *, int);
-/* from ns_internal.h */
-extern int __s_api_prepend_automountmapname_to_dn(
- const char *, char **, ns_ldap_error_t **);
static char *inputbasedn = NULL;
static char *databasetype = NULL;
@@ -439,7 +436,13 @@ addentry(void *entry, int mod)
if (eres->status == LDAP_ALREADY_EXISTS ||
eres->status == LDAP_NO_SUCH_OBJECT)
rc = eres->status;
- else {
+ else if (eres->status == LDAP_INSUFFICIENT_ACCESS) {
+ (void) fprintf(stderr,
+ gettext("The user does not have permission"
+ " to add/modify entries\n"));
+ perr(eres);
+ exit(1);
+ } else {
rc = 1;
perr(eres);
}
@@ -2110,20 +2113,24 @@ dump_aliases(ns_ldap_result_t *res)
* /etc/publickey
*/
+static char *h_errno2str(int h_errno);
+
static int
genent_publickey(char *line, int (*cback)())
{
char buf[BUFSIZ+1], tmpbuf[BUFSIZ+1], cname[BUFSIZ+1];
char *t, *p, *tmppubkey, *tmpprivkey;
entry_col ecol[3];
- int buflen, uid, retval = 1;
+ int buflen, uid, retval = 1, errnum = 0;
struct passwd *pwd;
- char auth_type[BUFSIZ+1];
+ char auth_type[BUFSIZ+1], *dot;
keylen_t keylen;
algtype_t algtype;
struct _ns_pubkey data;
struct hostent *hp;
struct in_addr in;
+ struct in6_addr in6;
+ char abuf[INET6_ADDRSTRLEN];
/*
* don't clobber our argument
@@ -2179,17 +2186,48 @@ genent_publickey(char *line, int (*cback)())
(void) strcpy(cname, pwd->pw_name);
data.hostcred = NS_HOSTCRED_FALSE;
} else {
- if ((hp = gethostbyname(tmpbuf)) == 0) {
+ if ((hp = getipnodebyname(tmpbuf, AF_INET6,
+ AI_ALL | AI_V4MAPPED, &errnum)) == NULL) {
(void) fprintf(stderr,
- gettext("can't map hostname %s to hostaddress, skipping\n"),
- tmpbuf);
+ gettext("can't map hostname %s to hostaddress, "
+ "errnum %d %s skipping\n"), tmpbuf, errnum,
+ h_errno2str(errnum));
return (GENENT_OK);
}
- (void) memcpy((char *)&in.s_addr, hp->h_addr_list[0],
- sizeof (in));
+ (void) memcpy((char *)&in6.s6_addr, hp->h_addr_list[0],
+ hp->h_length);
+ if (IN6_IS_ADDR_V4MAPPED(&in6) ||
+ IN6_IS_ADDR_V4COMPAT(&in6)) {
+ IN6_V4MAPPED_TO_INADDR(&in6, &in);
+ if (inet_ntop(AF_INET, (const void *)&in, abuf,
+ INET6_ADDRSTRLEN) == NULL) {
+ (void) fprintf(stderr,
+ gettext("can't convert IPV4 address of"
+ " hostname %s to string, "
+ "skipping\n"), tmpbuf);
+ return (GENENT_OK);
+ }
+ } else {
+ if (inet_ntop(AF_INET6, (const void *)&in6, abuf,
+ INET6_ADDRSTRLEN) == NULL) {
+ (void) fprintf(stderr,
+ gettext("can't convert IPV6 address of"
+ " hostname %s to string, "
+ "skipping\n"), tmpbuf);
+ return (GENENT_OK);
+ }
+ }
data.hostcred = NS_HOSTCRED_TRUE;
+ /*
+ * tmpbuf could be an alias, use hp->h_name instead.
+ * hp->h_name is in FQDN format, so extract 1st field.
+ */
+ if ((dot = strchr(hp->h_name, '.')) != NULL)
+ *dot = '\0';
(void) snprintf(cname, sizeof (cname),
- "%s+ipHostNumber=%s", tmpbuf, inet_ntoa(in));
+ "%s+ipHostNumber=%s", hp->h_name, abuf);
+ if (dot)
+ *dot = '.';
}
ecol[0].ec_value.ec_value_val = cname;
@@ -2233,7 +2271,16 @@ genent_publickey(char *line, int (*cback)())
/*
* auth_type (col 1)
*/
- if (!(__nis_keyalg2authtype(keylen, algtype, auth_type,
+ if (AUTH_DES_KEY(keylen, algtype))
+ /*
+ * {DES} and {DH192-0} means same thing.
+ * However, nisplus uses "DES" and ldap uses "DH192-0"
+ * internally.
+ * See newkey(1M), __nis_mechalias2authtype() which is
+ * called by __nis_keyalg2authtype() and getkey_ldap_g()
+ */
+ (void) strlcpy(auth_type, "DH192-0", BUFSIZ+1);
+ else if (!(__nis_keyalg2authtype(keylen, algtype, auth_type,
MECH_MAXATNAME))) {
(void) fprintf(stderr,
gettext("Could not convert algorithm type to "
@@ -2291,7 +2338,6 @@ genent_publickey(char *line, int (*cback)())
free(data.pubkey);
free(data.privkey);
return (GENENT_OK);
-
}
static void
@@ -3816,7 +3862,7 @@ main(int argc, char **argv)
int rc;
int ldaprc;
int authstried = 0;
- int supportedauth = 0;
+ int supportedauth = 0, gssapi = 0;
int op = OP_ADD;
char *ttype, *authmech = 0, *etcfile = 0;
char ps[LDAP_MAXNAMELEN]; /* Temporary password variable */
@@ -3916,6 +3962,15 @@ main(int argc, char **argv)
authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
supportedauth = 1;
}
+ if (strcasecmp(authmech, "sasl/GSSAPI") == 0) {
+ authority.auth.type = NS_LDAP_AUTH_SASL;
+ authority.auth.tlstype = NS_LDAP_TLS_SASL;
+ authority.auth.saslmech = NS_LDAP_SASL_GSSAPI;
+ authority.auth.saslopt = NS_LDAP_SASLOPT_PRIV |
+ NS_LDAP_SASLOPT_INT;
+ gssapi = 1;
+ supportedauth = 1;
+ }
if (strcasecmp(authmech, "tls:simple") == 0) {
authority.auth.type = NS_LDAP_AUTH_TLS;
authority.auth.tlstype = NS_LDAP_TLS_SIMPLE;
@@ -3944,6 +3999,23 @@ main(int argc, char **argv)
}
}
+ if (!gssapi && authority.cred.unix_cred.userID == NULL &&
+ op != OP_DUMP) {
+ /* This is not an optional parameter. Exit */
+ (void) fprintf(stderr,
+ gettext("Distinguished Name to bind to directory"
+ " must be specified. use option -D.\n"));
+ exit(1);
+ }
+
+ if (!gssapi && authority.cred.unix_cred.passwd == NULL &&
+ op != OP_DUMP) {
+ /* If password is not specified, then prompt user for it. */
+ password = getpassphrase("Enter password:");
+ (void) strcpy(ps, password);
+ authority.cred.unix_cred.passwd = strdup(ps);
+ }
+
if (authmech == NULL) {
ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
&errorp);
@@ -3977,6 +4049,21 @@ main(int argc, char **argv)
"-a option"));
exit(1);
}
+ if (authority.auth.saslmech == NS_LDAP_SASL_GSSAPI &&
+ authority.cred.unix_cred.passwd != NULL &&
+ authority.cred.unix_cred.userID != NULL) {
+ /*
+ * -a is not specified and the auth method sasl/GSSAPI
+ * is defined in the configuration of the ldap profile.
+ * Even -D and -w is provided it's not valid usage.
+ */
+
+ (void) fprintf(stderr,
+ gettext("The default authentication is sasl/GSSAPI.\n"
+ "The bind DN and and password is not allowed."
+ "\n"));
+ exit(1);
+ }
}
ttype = argv[optind++];
@@ -4223,3 +4310,23 @@ static int get_basedn(char *service, char **basedn) {
return (NS_LDAP_SUCCESS);
}
}
+static char *
+h_errno2str(int h_errno) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ return ("HOST_NOT_FOUND");
+ break;
+ case TRY_AGAIN:
+ return ("TRY_AGAIN");
+ break;
+ case NO_RECOVERY:
+ return ("NO_RECOVERY");
+ break;
+ case NO_DATA:
+ return ("NO_DATA");
+ break;
+ default:
+ break;
+ }
+ return ("UNKNOWN_ERROR");
+}
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapclient.c b/usr/src/cmd/ldap/ns_ldap/ldapclient.c
index 0f3666de6d..6e507d2c1c 100644
--- a/usr/src/cmd/ldap/ns_ldap/ldapclient.c
+++ b/usr/src/cmd/ldap/ns_ldap/ldapclient.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -114,17 +113,10 @@
#include <limits.h>
#include <locale.h>
#include <syslog.h>
-#include "../../../lib/libsldap/common/ns_sldap.h"
#include <libscf.h>
#include <assert.h>
-/*
- * We need ns_internal.h for the #defines of:
- * NSCREDFILE, NSCONFIGFILE
- * and the function prototypes of:
- * __ns_ldap_setServer(), __ns_ldap_LoadConfiguration(),
- * __ns_ldap_DumpConfiguration(), __ns_ldap_DumpLdif()
- */
-#include "../../../lib/libsldap/common/ns_internal.h"
+#include "ns_sldap.h"
+#include "ns_internal.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SUNW_OST_OSCMD"
@@ -294,7 +286,7 @@ static void clientopts_free(clientopts_t *list);
extern ns_ldap_error_t *__ns_ldap_print_config(int);
extern void __ns_ldap_default_config();
-extern int __ns_ldap_download(char *, char *, char *, ns_ldap_error_t **);
+extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
/* Function prototypes (these could be static) */
static void usage(void);
@@ -562,9 +554,9 @@ main(int argc, char **argv)
if ((retcode == CLIENT_SUCCESS) ||
(retcode == CLIENT_ERR_FAIL) ||
(retcode == CLIENT_ERR_CREDENTIAL))
- exit(retcode);
+ return (retcode);
else
- exit(CLIENT_ERR_FAIL);
+ return (CLIENT_ERR_FAIL);
}
static int
@@ -597,6 +589,7 @@ static int
client_uninit(clientopts_t *arglist)
{
int retcode = CLIENT_SUCCESS;
+ ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
if (mode_verbose) {
CLIENT_FPUTS(
@@ -613,7 +606,13 @@ client_uninit(clientopts_t *arglist)
return (CLIENT_ERR_FAIL);
}
+ (void) __ns_ldap_self_gssapi_config(&config);
+
retcode = stop_services(STATE_SAVE);
+
+ if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
+ (void) system("/usr/sbin/cryptoadm enable metaslot");
+
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Errors stopping network services.\n"), stderr);
@@ -1451,7 +1450,7 @@ client_init(clientopts_t *arglist)
/* Get and set profile params */
retcode = __ns_ldap_download(
- arglist->profileName,
+ (const char *)arglist->profileName,
arglist->defaultServerList,
nisBaseDN,
&errorp);
@@ -1852,11 +1851,13 @@ stop_services(int saveState)
static int
start_services(int flag)
{
- int sysret, retcode = CLIENT_SUCCESS;
+ int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS;
FILE *domain_fp;
char domainname[BUFSIZ];
char cmd_domain_start[BUFSIZ];
int domainlen;
+ ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
+ ns_ldap_error_t *errorp = NULL;
if (mode_verbose) {
CLIENT_FPUTS(gettext("Starting network services\n"), stderr);
@@ -1894,8 +1895,8 @@ start_services(int flag)
if (domainname[domainlen-1] == '\n')
domainname[domainlen-1] = 0;
/* buffer size is checked above */
- (void) sprintf(cmd_domain_start, "%s %s %s", CMD_DOMAIN_START,
- domainname, TO_DEV_NULL);
+ (void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s",
+ CMD_DOMAIN_START, domainname, TO_DEV_NULL);
}
/*
@@ -1916,9 +1917,42 @@ start_services(int flag)
retcode = CLIENT_ERR_FAIL;
}
- if (start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
+ if ((rc = __ns_ldap_self_gssapi_config(&config)) !=
+ NS_LDAP_SUCCESS) {
+ CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
+ "checking sasl/GSSAPI configuration\n"),
+ rc);
retcode = CLIENT_ERR_FAIL;
+ }
+
+ if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
+ rc = __ns_ldap_check_dns_preq(
+ 1, mode_verbose, mode_quiet,
+ NSSWITCH_LDAP, config, &errorp);
+ if (errorp)
+ (void) __ns_ldap_freeError(&errorp);
+
+ if (rc != NS_LDAP_SUCCESS)
+ retcode = CLIENT_ERR_FAIL;
+ }
+
+ if (rc == NS_LDAP_SUCCESS &&
+ start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
+ retcode = CLIENT_ERR_FAIL;
+
+ if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
+ rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) {
+ rc = __ns_ldap_check_gssapi_preq(
+ 1, mode_verbose, mode_quiet, config,
+ &errorp);
+ if (errorp)
+ (void) __ns_ldap_freeError(&errorp);
+
+ if (rc != NS_LDAP_SUCCESS)
+ retcode = CLIENT_ERR_FAIL;
+
+ }
/* No YP or NIS+ after init */
/*
* Or we can be starting services after an uninit or error
@@ -1973,6 +2007,17 @@ start_services(int flag)
!(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(NSCD_FMRI, B_TRUE);
+#if 0
+ if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
+ retcode == CLIENT_SUCCESS &&
+ !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) {
+ CLIENT_FPRINTF(stderr, "start: %s\n",
+ gettext("self/sasl/GSSAPI is configured"
+ " but nscd is not online"));
+ retcode = CLIENT_ERR_FAIL;
+ }
+#endif
+
if ((enableFlag & SENDMAIL_ON) &&
!(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(SENDMAIL_FMRI, B_TRUE);
diff --git a/usr/src/cmd/ldap/ns_ldap/mapping.c b/usr/src/cmd/ldap/ns_ldap/mapping.c
index 470ca20628..e5b7d26575 100644
--- a/usr/src/cmd/ldap/ns_ldap/mapping.c
+++ b/usr/src/cmd/ldap/ns_ldap/mapping.c
@@ -74,6 +74,15 @@ static struct mapping maplist[] = {
{NULL, NULL, NULL, NULL}
};
+#define PROF_ATTR_FILTER \
+ "(&(objectclass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*))%s)"
+#define TNRHTP_FILTER \
+ "(&(objectclass=ipTnetTemplate)(!(objectclass=ipTnetHost))%s)"
+#define OC_FILTER "objectclass=%s"
+#define OC_FLEN 15
+#define OC_FILTER2 "(&(objectclass=%s)%s)"
+#define OC_FLEN2 22
+
/* Malloc and print error message in case of failure */
#define MALLOC(ptr, len) \
if ((ptr = (char *)malloc(len)) == NULL) { \
@@ -378,6 +387,7 @@ set_filter(char **key, char *database, char **udata)
char *keyfilter;
int i, filterlen, udatalen;
int rc, v2 = 1;
+ int dbpf, dbtp;
void **paramVal = NULL;
ns_ldap_error_t *errorp = NULL;
short nomem;
@@ -415,32 +425,69 @@ set_filter(char **key, char *database, char **udata)
*/
for (i = 2; maplist[i].database != NULL; i++) {
if (strcasecmp(database, maplist[i].database) == SAME) {
+ dbpf = 0, dbtp = 0;
+ if (strcasecmp(database, "prof_attr") == 0)
+ dbpf = 1;
+ else if (strcasecmp(database, "tnrhtp") == 0)
+ dbtp = 1;
if ((keyfilter = set_keys(key, maplist[i].def_type))
== NULL) {
- filterlen = strlen(maplist[i].objectclass) + 13;
+ filterlen = strlen(maplist[i].objectclass);
udatalen = 3;
+ if (dbpf)
+ filterlen += strlen(PROF_ATTR_FILTER)
+ + 1;
+ else if (dbtp)
+ filterlen += strlen(TNRHTP_FILTER) + 1;
+ else
+ filterlen += OC_FLEN;
+
MALLOC_FILTER_UDATA(filter, filterlen, userdata,
udatalen, nomem);
- if (!nomem) {
+ if (nomem)
+ goto done;
+ if (dbpf)
+ (void) snprintf(filter, filterlen,
+ PROF_ATTR_FILTER, "");
+ else if (dbtp)
+ (void) snprintf(filter, filterlen,
+ TNRHTP_FILTER, "");
+ else
(void) snprintf(filter, filterlen,
- "objectclass=%s",
+ OC_FILTER,
maplist[i].objectclass);
- (void) snprintf(userdata, udatalen,
- "%%s");
- }
+
+ (void) snprintf(userdata, udatalen, "%%s");
} else {
filterlen = strlen(maplist[i].objectclass) +
- strlen(keyfilter) + 18;
+ strlen(keyfilter);
+ if (dbpf)
+ filterlen += strlen(PROF_ATTR_FILTER)
+ + 1;
+ else if (dbtp)
+ filterlen += strlen(TNRHTP_FILTER) + 1;
+ else
+ filterlen += OC_FLEN2;
+
udatalen = strlen(keyfilter) + 8;
MALLOC_FILTER_UDATA(filter, filterlen, userdata,
udatalen, nomem);
- if (!nomem) {
+ if (nomem)
+ goto done;
+ if (dbpf)
(void) snprintf(filter, filterlen,
- "(&(objectclass=%s)%s)",
- maplist[i].objectclass, keyfilter);
- (void) snprintf(userdata, udatalen,
- "(&(%%s)%s)", keyfilter);
- }
+ PROF_ATTR_FILTER, keyfilter);
+ else if (dbtp)
+ (void) snprintf(filter, filterlen,
+ TNRHTP_FILTER, keyfilter);
+ else
+ (void) snprintf(filter, filterlen,
+ OC_FILTER2,
+ maplist[i].objectclass,
+ keyfilter);
+
+ (void) snprintf(userdata, udatalen,
+ "(&(%%s)%s)", keyfilter);
}
goto done;
}
diff --git a/usr/src/cmd/ldapcachemgr/Makefile b/usr/src/cmd/ldapcachemgr/Makefile
index fa38464f75..6b4e86f223 100644
--- a/usr/src/cmd/ldapcachemgr/Makefile
+++ b/usr/src/cmd/ldapcachemgr/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -62,7 +61,7 @@ LINTOUT= lint.out
# GPROF_FLAG= -xpg
# DEBUG_FLAG= -g
-LDLIBS += -lsldap -lldap
+LDLIBS += -lsldap -lldap -lnsl
# install macros and rule
#
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr.c b/usr/src/cmd/ldapcachemgr/cachemgr.c
index d97b8d08c1..2fd9f5bbc0 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -214,7 +213,7 @@ server_tsd_bind(void *arg)
*/
(void) thr_setspecific(server_key, value);
- door_return(NULL, 0, NULL, 0);
+ (void) door_return(NULL, 0, NULL, 0);
return (value);
}
@@ -470,7 +469,7 @@ main(int argc, char ** argv)
* Establish our own server thread pool
*/
- door_server_create(server_create);
+ (void) door_server_create(server_create);
if (thr_keycreate(&server_key, server_destroy) != 0) {
logit("thr_keycreate() call failed\n");
syslog(LOG_ERR,
@@ -595,6 +594,8 @@ main(int argc, char ** argv)
while (1) {
(void) pause();
}
+ /* NOTREACHED */
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
}
@@ -679,7 +680,7 @@ switcher(void *cookie, char *argp, size_t arg_size,
u.data.ldap_ret.ldap_bufferbytesused = sizeof (ldap_return_t);
break;
}
- door_return((char *)&u.data,
+ (void) door_return((char *)&u.data,
u.data.ldap_ret.ldap_bufferbytesused, NULL, 0);
}
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
index 2a83c2d215..3541102ab6 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,6 +45,9 @@
#include <lber.h>
#include <ldap.h>
#include <ctype.h> /* tolower */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include "cachemgr.h"
#include "solaris-priv.h"
@@ -130,6 +132,7 @@ typedef enum {
typedef struct server_info_ext {
char *addr;
+ char *hostname;
char *rootDSE_data;
char *errormsg;
info_rw_t type;
@@ -449,6 +452,10 @@ sync_current_with_update_copy(server_info_t *info)
free(info->sinfo[0].addr);
info->sinfo[0].addr = NULL;
+ if (info->sinfo[0].hostname)
+ free(info->sinfo[0].hostname);
+ info->sinfo[0].hostname = NULL;
+
if (info->sinfo[0].rootDSE_data)
free(info->sinfo[0].rootDSE_data);
info->sinfo[0].rootDSE_data = NULL;
@@ -475,6 +482,8 @@ sync_current_with_update_copy(server_info_t *info)
*/
if (info->sinfo[1].addr)
info->sinfo[0].addr = strdup(info->sinfo[1].addr);
+ if (info->sinfo[1].hostname)
+ info->sinfo[0].hostname = strdup(info->sinfo[1].hostname);
if (info->sinfo[1].rootDSE_data)
info->sinfo[0].rootDSE_data =
strdup(info->sinfo[1].rootDSE_data);
@@ -563,7 +572,6 @@ getldap_get_rootDSE(void *arg)
sync_current_with_update_copy(serverInfo);
thr_exit((void *) -1);
}
-
ldap_set_option(ld,
LDAP_OPT_PROTOCOL_VERSION, &ldapVersion);
ldap_set_option(ld,
@@ -810,6 +818,8 @@ getldap_init_serverInfo(server_info_t **head)
INFO_SERVER_UP;
info->sinfo[1].prev_server_status =
INFO_SERVER_UP;
+ info->sinfo[0].hostname = NULL;
+ info->sinfo[1].hostname = NULL;
info->sinfo[0].rootDSE_data = NULL;
info->sinfo[1].rootDSE_data = NULL;
info->sinfo[0].errormsg = NULL;
@@ -846,6 +856,10 @@ getldap_destroy_serverInfo(server_info_t *head)
free(info->sinfo[0].addr);
if (info->sinfo[1].addr)
free(info->sinfo[1].addr);
+ if (info->sinfo[0].hostname)
+ free(info->sinfo[0].hostname);
+ if (info->sinfo[1].hostname)
+ free(info->sinfo[1].hostname);
if (info->sinfo[0].rootDSE_data)
free(info->sinfo[0].rootDSE_data);
if (info->sinfo[1].rootDSE_data)
@@ -954,11 +968,123 @@ getldap_set_serverInfo(server_info_t *head,
}
/*
+ * Convert an IP to a host name
+ */
+static int
+getldap_ip2hostname(char *ipaddr, char **hostname) {
+ struct in_addr in;
+ struct in6_addr in6;
+ struct hostent *hp = NULL;
+ char *start = NULL, *end = NULL, delim = '\0';
+ char *port = NULL, *addr = NULL;
+ int error_num = 0, len = 0;
+
+ if (ipaddr == NULL || hostname == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+ *hostname = NULL;
+ if ((addr = strdup(ipaddr)) == NULL)
+ return (NS_LDAP_MEMORY);
+
+ if (addr[0] == '[') {
+ /*
+ * Assume it's [ipv6]:port
+ * Extract ipv6 IP
+ */
+ start = &addr[1];
+ if ((end = strchr(addr, ']')) != NULL) {
+ *end = '\0';
+ delim = ']';
+ if (*(end + 1) == ':')
+ /* extract port */
+ port = end + 2;
+ } else {
+ return (NS_LDAP_INVALID_PARAM);
+ }
+ } else if ((end = strchr(addr, ':')) != NULL) {
+ /* assume it's ipv4:port */
+ *end = '\0';
+ delim = ':';
+ start = addr;
+ port = end + 1;
+ } else
+ /* No port */
+ start = addr;
+
+
+ if (inet_pton(AF_INET, start, &in) == 1) {
+ /* IPv4 */
+ hp = getipnodebyaddr((char *)&in,
+ sizeof (struct in_addr), AF_INET, &error_num);
+ if (hp && hp->h_name) {
+ /* hostname + '\0' */
+ len = strlen(hp->h_name) + 1;
+ if (port)
+ /* ':' + port */
+ len += strlen(port) + 1;
+ if ((*hostname = malloc(len)) == NULL) {
+ free(addr);
+ freehostent(hp);
+ return (NS_LDAP_MEMORY);
+ }
+
+ if (port)
+ (void) snprintf(*hostname, len, "%s:%s",
+ hp->h_name, port);
+ else
+ (void) strlcpy(*hostname, hp->h_name, len);
+
+ free(addr);
+ freehostent(hp);
+ return (NS_LDAP_SUCCESS);
+ } else {
+ return (NS_LDAP_NOTFOUND);
+ }
+ } else if (inet_pton(AF_INET6, start, &in6) == 1) {
+ /* IPv6 */
+ hp = getipnodebyaddr((char *)&in6,
+ sizeof (struct in6_addr), AF_INET6, &error_num);
+ if (hp && hp->h_name) {
+ /* hostname + '\0' */
+ len = strlen(hp->h_name) + 1;
+ if (port)
+ /* ':' + port */
+ len += strlen(port) + 1;
+ if ((*hostname = malloc(len)) == NULL) {
+ free(addr);
+ freehostent(hp);
+ return (NS_LDAP_MEMORY);
+ }
+
+ if (port)
+ (void) snprintf(*hostname, len, "%s:%s",
+ hp->h_name, port);
+ else
+ (void) strlcpy(*hostname, hp->h_name, len);
+
+ free(addr);
+ freehostent(hp);
+ return (NS_LDAP_SUCCESS);
+ } else {
+ return (NS_LDAP_NOTFOUND);
+ }
+ } else {
+ /*
+ * A hostname
+ * Return it as is
+ */
+ if (end)
+ *end = delim;
+ *hostname = addr;
+ return (NS_LDAP_SUCCESS);
+ }
+}
+/*
* getldap_get_serverInfo processes the GETLDAPSERVER door request passed
* to this function from getldap_serverInfo_op().
* input:
* a buffer containing an empty string (e.g., input[0]='\0';) or a string
- * as the "input" in printf(input, "%s%s%s", req, DOORLINESEP, addr);
+ * as the "input" in printf(input, "%s%s%s%s", req, addrtype, DOORLINESEP,
+ * addr);
* where addr is the address of a server and
* req is one of the following:
* NS_CACHE_NEW: send a new server address, addr is ignored.
@@ -966,6 +1092,10 @@ getldap_set_serverInfo(server_info_t *head,
* NS_CACHE_NEXT: send the next one, keep addr on list.
* NS_CACHE_WRITE: send a non-replica server, if possible, if not, same
* as NS_CACHE_NEXT.
+ * addrtype:
+ * NS_CACHE_ADDR_IP: return server address as is, this is default.
+ * NS_CACHE_ADDR_HOSTNAME: return server addess as FQDN format, only
+ * self credential case requires such format.
* output:
* a buffer containing server info in the following format:
* serveraddress DOORLINESEP [ attr=value [DOORLINESEP attr=value ]...]
@@ -982,7 +1112,9 @@ getldap_get_serverInfo(server_info_t *head, char *input,
char *addr = NULL;
char *req = NULL;
char req_new[] = NS_CACHE_NEW;
- int matched = FALSE, len;
+ char addr_type[] = NS_CACHE_ADDR_IP;
+ int matched = FALSE, len, rc = 0;
+ char *ret_addr = NULL;
if (current_admin.debug_level >= DBG_ALL) {
logit("getldap_get_serverInfo()...\n");
@@ -1010,8 +1142,12 @@ getldap_get_serverInfo(server_info_t *head, char *input,
req = req_new;
if (input[0] != '\0') {
req = input;
+ /* Save addr type flag */
+ addr_type[0] = input[1];
input[strlen(NS_CACHE_NEW)] = '\0';
- addr = input + strlen(DOORLINESEP) + strlen(NS_CACHE_NEW);
+ /* skip acion type flag, addr type flag and DOORLINESEP */
+ addr = input + strlen(DOORLINESEP) + strlen(NS_CACHE_NEW)
+ + strlen(NS_CACHE_ADDR_IP);
}
/*
* if NS_CACHE_NEW,
@@ -1122,7 +1258,34 @@ getldap_get_serverInfo(server_info_t *head, char *input,
}
if (server) {
- len = strlen(server->sinfo[0].addr) +
+ if (strcmp(addr_type, NS_CACHE_ADDR_HOSTNAME) == 0) {
+ /*
+ * In SASL/GSSAPI case, a hostname is required for
+ * Kerberos's service principal.
+ * e.g.
+ * ldap/foo.sun.com@SUN.COM
+ */
+ if (server->sinfo[0].hostname == NULL) {
+ rc = getldap_ip2hostname(server->sinfo[0].addr,
+ &server->sinfo[0].hostname);
+ if (rc != NS_LDAP_SUCCESS) {
+ (void) mutex_unlock(&info->mutex[0]);
+ return (rc);
+ }
+ if (current_admin.debug_level >= DBG_ALL) {
+ logit("getldap_get_serverInfo: "
+ "%s is converted to %s\n",
+ server->sinfo[0].addr,
+ server->sinfo[0].hostname);
+ }
+ }
+ ret_addr = server->sinfo[0].hostname;
+
+ } else
+ ret_addr = server->sinfo[0].addr;
+
+
+ len = strlen(ret_addr) +
strlen(server->sinfo[0].rootDSE_data) +
strlen(DOORLINESEP) + 1;
*output = (char *)malloc(len);
@@ -1131,7 +1294,7 @@ getldap_get_serverInfo(server_info_t *head, char *input,
return (NS_LDAP_MEMORY);
}
(void) snprintf(*output, len, "%s%s%s",
- server->sinfo[0].addr, DOORLINESEP,
+ ret_addr, DOORLINESEP,
server->sinfo[0].rootDSE_data);
server->sinfo[0].info_status = INFO_STATUS_OLD;
(void) mutex_unlock(&info->mutex[0]);
@@ -1927,7 +2090,6 @@ getldap_serverInfo_op(info_op_t op, char *input, char **output)
} else
(void) getldap_get_serverInfo(serverInfo_old,
input, output, &server_removed);
-
(void) rw_unlock(&info_lock_old);
/*
@@ -2354,9 +2516,9 @@ update_from_profile()
logit("update_from_profile: reset profile TTL to %d"
" seconds\n",
current_admin.ldap_stat.ldap_ttl);
- logit("update_from_profile: expire time %d "
+ logit("update_from_profile: expire time %ld "
"seconds\n",
- *ptr->paramList[NS_LDAP_EXP_P].ns_pi);
+ ptr->paramList[NS_LDAP_EXP_P].ns_tm);
}
/* set ptr as current_config */
@@ -2370,6 +2532,7 @@ update_from_profile()
rc = -1;
}
(void) rw_unlock(&ldap_lock);
+
return (rc);
}
@@ -2416,7 +2579,8 @@ perform_update(void)
ns_ldap_error_t *error;
struct timeval tp;
char buf[20];
- int rc;
+ int rc, rc1;
+ ns_ldap_self_gssapi_config_t config;
if (current_admin.debug_level >= DBG_ALL) {
logit("perform_update()...\n");
@@ -2450,7 +2614,7 @@ perform_update(void)
&error) != NS_LDAP_SUCCESS) {
logit("Error: __ns_ldap_setParam failed, status: %d "
"message: %s\n", error->status, error->message);
- __ns_ldap_freeError(&error);
+ (void) __ns_ldap_freeError(&error);
return;
}
@@ -2478,6 +2642,23 @@ perform_update(void)
/* statistics: previous refresh time */
prev_refresh_time = tp.tv_sec;
}
+ rc1 = __ns_ldap_self_gssapi_config(&config);
+ if (rc1 == NS_LDAP_SUCCESS) {
+ if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
+ rc1 = __ns_ldap_check_all_preq(0, 0, 0, config, &error);
+ (void) __ns_ldap_freeError(&error);
+ if (rc1 != NS_LDAP_SUCCESS) {
+ logit("Error: Check on self credential "
+ "prerquesites failed: %d\n",
+ rc1);
+ exit(rc1);
+ }
+ }
+ } else {
+ logit("Error: Failed to get self credential configuration %d\n",
+ rc1);
+ exit(rc1);
+ }
(void) rw_rdlock(&ldap_lock);
if ((error = __ns_ldap_DumpConfiguration(NSCONFIGREFRESH)) != NULL) {
@@ -2498,6 +2679,7 @@ perform_update(void)
logit("Error: unlink failed - errno: %d\n", errno);
if (rename(NSCREDREFRESH, NSCREDFILE) != 0)
logit("Error: unlink failed - errno: %d\n", errno);
+
(void) rw_unlock(&ldap_lock);
}
diff --git a/usr/src/cmd/nscd/Makefile b/usr/src/cmd/nscd/Makefile
index 4932374ed6..c3f749bc77 100644
--- a/usr/src/cmd/nscd/Makefile
+++ b/usr/src/cmd/nscd/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
+# Makefile for name service cache daemon
+#
PROG= nscd
NISPROG= nscd_nischeck
@@ -39,9 +40,21 @@ $(ROOTMANIFEST) := FILEMODE= 444
$(ROOTMANIFESTDIR)/%: %
$(INS.file)
-OBJS= server.o getpw.o getgr.o gethost.o getnode.o hash.o \
- nscd_biggest.o nscd_parse.o nscd_wait.o \
- getexec.o getprof.o getuser.o attrstr.o
+OBJS= server.o getpw.o getgr.o gethost.o getnode.o \
+ getether.o getrpc.o getproto.o getnet.o \
+ getbootp.o getauuser.o getauth.o getserv.o \
+ getnetmasks.o getprinter.o getproject.o \
+ getexec.o getprof.o getuser.o cache.o \
+ nscd_biggest.o nscd_wait.o \
+ nscd_init.o nscd_access.o nscd_cfgfile.o nscd_config.o \
+ nscd_dbimpl.o nscd_getentctx.o nscd_intaddr.o \
+ nscd_log.o nscd_nswconfig.o nscd_nswstate.o nscd_nswcfgst.o \
+ nscd_seqnum.o nscd_smfmonitor.o \
+ nscd_switch.o nscd_nswparse.o nscd_initf.o nscd_selfcred.o \
+ nscd_frontend.o nscd_admin.o nscd_door.o \
+ gettnrhtp.o gettnrhdb.o
+
+
NISOBJS= nscd_nischeck.o
@@ -51,13 +64,18 @@ SRCS= ${OBJS:%.o=%.c}
NISSRC= ${NISOBJS:%.o=%.c}
-CPPFLAGS += -D_REENTRANT -DSUN_THREADS
+CPPFLAGS += -D_REENTRANT -DSUN_THREADS \
+ -I../../lib/libc/port/gen -I../../lib/libc/inc \
+ -I../../lib/libsldap/common
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+LINTFLAGS += -erroff=E_NAME_USED_NOT_DEF2
+LINTFLAGS += -erroff=E_NAME_DEF_NOT_USED2
# TCOV_FLAG= -ql
# GPROF_FLAG= -xpg
# DEBUG_FLAG= -g
-$(PROG) := LDLIBS += -lresolv -lnsl -lsocket -lumem -lscf
+$(PROG) := LDLIBS += -lresolv -lnsl -lsocket -lumem -lscf -lavl -lgss
$(NISPROG) := LDLIBS += -lnsl
# install macros and rule
@@ -78,8 +96,6 @@ ${NISPROG}: ${NISOBJS}
${LINK.c} ${OPT} -o $@ ${NISOBJS} ${LDLIBS}
${POST_PROCESS}
-lint := LINTFLAGS=-x -b -u
-
lint:
$(LINT.c) ${SRCS}
diff --git a/usr/src/cmd/nscd/cache.c b/usr/src/cmd/nscd/cache.c
new file mode 100644
index 0000000000..a8f6f43515
--- /dev/null
+++ b/usr/src/cmd/nscd/cache.c
@@ -0,0 +1,2378 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Cache routines for nscd
+ */
+#include <assert.h>
+#include <errno.h>
+#include <memory.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <ucred.h>
+#include <nss_common.h>
+#include <locale.h>
+#include <ctype.h>
+#include <strings.h>
+#include <string.h>
+#include <umem.h>
+#include <fcntl.h>
+#include "cache.h"
+#include "nscd_door.h"
+#include "nscd_log.h"
+#include "nscd_config.h"
+#include "nscd_frontend.h"
+#include "nscd_switch.h"
+
+#define SUCCESS 0
+#define NOTFOUND -1
+#define SERVERERROR -2
+#define NOSERVER -3
+#define CONTINUE -4
+
+static nsc_db_t *nsc_get_db(nsc_ctx_t *, int);
+static nscd_rc_t lookup_cache(nsc_lookup_args_t *, nscd_cfg_cache_t *,
+ nss_XbyY_args_t *, char *, nsc_entry_t **);
+static uint_t reap_cache(nsc_ctx_t *, uint_t, uint_t);
+static void delete_entry(nsc_db_t *, nsc_ctx_t *, nsc_entry_t *);
+static void print_stats(nscd_cfg_stat_cache_t *);
+static void print_cfg(nscd_cfg_cache_t *);
+static int lookup_int(nsc_lookup_args_t *, int);
+
+#ifdef NSCD_DEBUG
+static void print_entry(nsc_db_t *, time_t, nsc_entry_t *);
+static void avl_dump(nsc_db_t *, time_t);
+static void hash_dump(nsc_db_t *, time_t);
+#endif /* NSCD_DEBUG */
+static nsc_entry_t *hash_find(nsc_db_t *, nsc_entry_t *, uint_t *, nscd_bool_t);
+
+static void queue_adjust(nsc_db_t *, nsc_entry_t *);
+static void queue_remove(nsc_db_t *, nsc_entry_t *);
+#ifdef NSCD_DEBUG
+static void queue_dump(nsc_db_t *, time_t);
+#endif /* NSCD_DEBUG */
+
+static int launch_update(nsc_lookup_args_t *);
+static void do_update(nsc_lookup_args_t *);
+static void getxy_keepalive(nsc_ctx_t *, nsc_db_t *, int, int);
+
+static void ctx_info(nsc_ctx_t *);
+static void ctx_info_nolock(nsc_ctx_t *);
+static void ctx_invalidate(nsc_ctx_t *);
+
+static void nsc_db_str_key_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static void nsc_db_int_key_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static void nsc_db_any_key_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+
+static int nsc_db_cis_key_compar(const void *, const void *);
+static int nsc_db_ces_key_compar(const void *, const void *);
+static int nsc_db_int_key_compar(const void *, const void *);
+
+static uint_t nsc_db_cis_key_gethash(nss_XbyY_key_t *, int);
+static uint_t nsc_db_ces_key_gethash(nss_XbyY_key_t *, int);
+static uint_t nsc_db_int_key_gethash(nss_XbyY_key_t *, int);
+
+static umem_cache_t *nsc_entry_cache;
+
+static nsc_ctx_t *init_cache_ctx(int);
+static void reaper(nsc_ctx_t *);
+static void revalidate(nsc_ctx_t *);
+
+static nss_status_t
+dup_packed_buffer(void *src, void *dst) {
+ nsc_lookup_args_t *s = (nsc_lookup_args_t *)src;
+ nsc_entry_t *d = (nsc_entry_t *)dst;
+ nss_pheader_t *sphdr = (nss_pheader_t *)s->buffer;
+ nss_pheader_t *dphdr = (nss_pheader_t *)d->buffer;
+ int slen, new_pbufsiz = 0;
+
+ if (NSCD_GET_STATUS(sphdr) != NSS_SUCCESS) {
+
+ /* no result, copy header only (status, errno, etc) */
+ slen = sphdr->data_off;
+ } else {
+ /*
+ * lookup result returned, data to copy is the packed
+ * header plus result (add 1 for the terminating NULL
+ * just in case)
+ */
+ slen = sphdr->data_off + sphdr->data_len + 1;
+ }
+
+ /* allocate cache packed buffer */
+ if (dphdr != NULL && d->bufsize <= slen && d->bufsize != 0) {
+ /* old buffer too small, free it */
+ free(dphdr);
+ d->buffer = NULL;
+ d->bufsize = 0;
+ dphdr = NULL;
+ }
+ if (dphdr == NULL) {
+ /* get new buffer */
+ dphdr = calloc(1, slen + 1);
+ if (dphdr == NULL)
+ return (NSS_ERROR);
+ d->buffer = dphdr;
+ d->bufsize = slen + 1;
+ new_pbufsiz = slen + 1;
+ }
+
+ (void) memcpy(dphdr, sphdr, slen);
+ if (new_pbufsiz != 0)
+ dphdr->pbufsiz = new_pbufsiz;
+
+ return (NSS_SUCCESS);
+}
+
+char *cache_name[CACHE_CTX_COUNT] = {
+ NSS_DBNAM_PASSWD,
+ NSS_DBNAM_GROUP,
+ NSS_DBNAM_HOSTS,
+ NSS_DBNAM_IPNODES,
+ NSS_DBNAM_EXECATTR,
+ NSS_DBNAM_PROFATTR,
+ NSS_DBNAM_USERATTR,
+ NSS_DBNAM_ETHERS,
+ NSS_DBNAM_RPC,
+ NSS_DBNAM_PROTOCOLS,
+ NSS_DBNAM_NETWORKS,
+ NSS_DBNAM_BOOTPARAMS,
+ NSS_DBNAM_AUDITUSER,
+ NSS_DBNAM_AUTHATTR,
+ NSS_DBNAM_SERVICES,
+ NSS_DBNAM_NETMASKS,
+ NSS_DBNAM_PRINTERS,
+ NSS_DBNAM_PROJECT,
+ NSS_DBNAM_TSOL_TP,
+ NSS_DBNAM_TSOL_RH
+};
+
+typedef void (*cache_init_ctx_t)(nsc_ctx_t *);
+static cache_init_ctx_t cache_init_ctx[CACHE_CTX_COUNT] = {
+ passwd_init_ctx,
+ group_init_ctx,
+ host_init_ctx,
+ ipnode_init_ctx,
+ exec_init_ctx,
+ prof_init_ctx,
+ user_init_ctx,
+ ether_init_ctx,
+ rpc_init_ctx,
+ proto_init_ctx,
+ net_init_ctx,
+ bootp_init_ctx,
+ auuser_init_ctx,
+ auth_init_ctx,
+ serv_init_ctx,
+ netmask_init_ctx,
+ printer_init_ctx,
+ project_init_ctx,
+ tnrhtp_init_ctx,
+ tnrhdb_init_ctx
+};
+
+nsc_ctx_t *cache_ctx_p[CACHE_CTX_COUNT] = { 0 };
+static nscd_cfg_stat_cache_t null_stats = { 0 };
+static nscd_cfg_global_cache_t global_cfg;
+
+/*
+ * Given database name 'dbname' find cache index
+ */
+int
+get_cache_idx(char *dbname) {
+ int i;
+ char *nsc_name;
+
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ nsc_name = cache_name[i];
+ if (strcmp(nsc_name, dbname) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+/*
+ * Given database name 'dbname' retrieve cache context,
+ * if not created yet, allocate and initialize it.
+ */
+static nscd_rc_t
+get_cache_ctx(char *dbname, nsc_ctx_t **ctx) {
+ int i;
+
+ *ctx = NULL;
+
+ i = get_cache_idx(dbname);
+ if (i == -1)
+ return (NSCD_INVALID_ARGUMENT);
+ if ((*ctx = cache_ctx_p[i]) == NULL) {
+ *ctx = init_cache_ctx(i);
+ if (*ctx == NULL)
+ return (NSCD_NO_MEMORY);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * Generate a log string to identify backend operation in debug logs
+ */
+static void
+nsc_db_str_key_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%s]", name, argp->key.name);
+}
+
+
+static void
+nsc_db_int_key_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%d]", name, argp->key.number);
+}
+
+/*ARGSUSED*/
+static void
+nsc_db_any_key_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s", name);
+}
+
+
+/*
+ * Returns cache based on dbop
+ */
+static nsc_db_t *
+nsc_get_db(nsc_ctx_t *ctx, int dbop) {
+ int i;
+
+ for (i = 0; i < ctx->db_count; i++) {
+ if (ctx->nsc_db[i] && dbop == ctx->nsc_db[i]->dbop)
+ return (ctx->nsc_db[i]);
+ }
+ return (NULL);
+}
+
+
+/*
+ * integer compare routine for _NSC_DB_INT_KEY
+ */
+static int
+nsc_db_int_key_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ return (_NSC_INT_KEY_CMP(e1->key.number, e2->key.number));
+}
+
+
+/*
+ * case sensitive name compare routine for _NSC_DB_CES_KEY
+ */
+static int
+nsc_db_ces_key_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ l1 = strlen(e1->key.name);
+ l2 = strlen(e2->key.name);
+ res = strncmp(e1->key.name, e2->key.name, (l1 > l2)?l1:l2);
+ return (_NSC_INT_KEY_CMP(res, 0));
+}
+
+
+/*
+ * case insensitive name compare routine _NSC_DB_CIS_KEY
+ */
+static int
+nsc_db_cis_key_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ l1 = strlen(e1->key.name);
+ l2 = strlen(e2->key.name);
+ res = strncasecmp(e1->key.name, e2->key.name, (l1 > l2)?l1:l2);
+ return (_NSC_INT_KEY_CMP(res, 0));
+}
+
+/*
+ * macro used to generate elf hashes for strings
+ */
+#define _NSC_ELF_STR_GETHASH(func, str, htsize, hval) \
+ hval = 0; \
+ while (*str) { \
+ uint_t g; \
+ hval = (hval << 4) + func(*str++); \
+ if ((g = (hval & 0xf0000000)) != 0) \
+ hval ^= g >> 24; \
+ hval &= ~g; \
+ } \
+ hval %= htsize;
+
+
+/*
+ * cis hash function
+ */
+uint_t
+cis_gethash(const char *key, int htsize) {
+ uint_t hval;
+ if (key == NULL)
+ return (0);
+ _NSC_ELF_STR_GETHASH(tolower, key, htsize, hval);
+ return (hval);
+}
+
+
+/*
+ * ces hash function
+ */
+uint_t
+ces_gethash(const char *key, int htsize) {
+ uint_t hval;
+ if (key == NULL)
+ return (0);
+ _NSC_ELF_STR_GETHASH(, key, htsize, hval);
+ return (hval);
+}
+
+
+/*
+ * one-at-a-time hash function
+ */
+uint_t
+db_gethash(const void *key, int len, int htsize) {
+ uint_t hval, i;
+ const char *str = key;
+
+ if (str == NULL)
+ return (0);
+
+ for (hval = 0, i = 0; i < len; i++) {
+ hval += str[i];
+ hval += (hval << 10);
+ hval ^= (hval >> 6);
+ }
+ hval += (hval << 3);
+ hval ^= (hval >> 11);
+ hval += (hval << 15);
+ return (hval % htsize);
+}
+
+
+/*
+ * case insensitive name gethash routine _NSC_DB_CIS_KEY
+ */
+static uint_t
+nsc_db_cis_key_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (cis_gethash(key->name, htsize));
+}
+
+
+/*
+ * case sensitive name gethash routine _NSC_DB_CES_KEY
+ */
+static uint_t
+nsc_db_ces_key_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (ces_gethash(key->name, htsize));
+}
+
+
+/*
+ * integer gethash routine _NSC_DB_INT_KEY
+ */
+static uint_t
+nsc_db_int_key_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(&key->number, sizeof (key->number), htsize));
+}
+
+
+/*
+ * Find entry in the hash table
+ * if cmp == nscd_true)
+ * return entry only if the keys match
+ * else
+ * return entry in the hash location without checking the keys
+ *
+ */
+static nsc_entry_t *
+hash_find(nsc_db_t *nscdb, nsc_entry_t *entry, uint_t *hash,
+ nscd_bool_t cmp) {
+
+ nsc_entry_t *hashentry;
+
+ if (nscdb->gethash)
+ *hash = nscdb->gethash(&entry->key, nscdb->htsize);
+ else
+ return (NULL);
+
+ hashentry = nscdb->htable[*hash];
+ if (cmp == nscd_false || hashentry == NULL)
+ return (hashentry);
+ if (nscdb->compar) {
+ if (nscdb->compar(entry, hashentry) == 0)
+ return (hashentry);
+ }
+ return (NULL);
+}
+
+
+#define HASH_REMOVE(nscdb, entry, hash, cmp) \
+ if (nscdb->htable) { \
+ if (entry == hash_find(nscdb, entry, &hash, cmp)) \
+ nscdb->htable[hash] = NULL; \
+ }
+
+
+#define HASH_INSERT(nscdb, entry, hash, cmp) \
+ if (nscdb->htable) { \
+ (void) hash_find(nscdb, entry, &hash, cmp); \
+ nscdb->htable[hash] = entry; \
+ }
+
+
+#ifdef NSCD_DEBUG
+static void
+print_entry(nsc_db_t *nscdb, time_t now, nsc_entry_t *entry) {
+ nss_XbyY_args_t args;
+ char whoami[512];
+
+ switch (entry->stats.status) {
+ case ST_NEW_ENTRY:
+ (void) fprintf(stdout, gettext("\t status: new entry\n"));
+ return;
+ case ST_UPDATE_PENDING:
+ (void) fprintf(stdout, gettext("\t status: update pending\n"));
+ return;
+ case ST_LOOKUP_PENDING:
+ (void) fprintf(stdout, gettext("\t status: lookup pending\n"));
+ return;
+ case ST_DISCARD:
+ (void) fprintf(stdout, gettext("\t status: discarded entry\n"));
+ return;
+ default:
+ if (entry->stats.timestamp < now)
+ (void) fprintf(stdout,
+ gettext("\t status: expired (%d seconds ago)\n"),
+ now - entry->stats.timestamp);
+ else
+ (void) fprintf(stdout,
+ gettext("\t status: valid (expiry in %d seconds)\n"),
+ entry->stats.timestamp - now);
+ break;
+ }
+ (void) fprintf(stdout, gettext("\t hits: %u\n"), entry->stats.hits);
+ args.key = entry->key;
+ (void) nscdb->getlogstr(nscdb->name, whoami, sizeof (whoami), &args);
+ (void) fprintf(stdout, "\t %s\n", whoami);
+}
+#endif /* NSCD_DEBUG */
+
+static void
+print_stats(nscd_cfg_stat_cache_t *statsp) {
+
+ (void) fprintf(stdout, gettext("\n\t STATISTICS:\n"));
+ (void) fprintf(stdout, gettext("\t positive hits: %lu\n"),
+ statsp->pos_hits);
+ (void) fprintf(stdout, gettext("\t negative hits: %lu\n"),
+ statsp->neg_hits);
+ (void) fprintf(stdout, gettext("\t positive misses: %lu\n"),
+ statsp->pos_misses);
+ (void) fprintf(stdout, gettext("\t negative misses: %lu\n"),
+ statsp->neg_misses);
+ (void) fprintf(stdout, gettext("\t total entries: %lu\n"),
+ statsp->entries);
+ (void) fprintf(stdout, gettext("\t queries queued: %lu\n"),
+ statsp->wait_count);
+ (void) fprintf(stdout, gettext("\t queries dropped: %lu\n"),
+ statsp->drop_count);
+ (void) fprintf(stdout, gettext("\t cache invalidations: %lu\n"),
+ statsp->invalidate_count);
+
+ _NSC_GET_HITRATE(statsp);
+ (void) fprintf(stdout, gettext("\t cache hit rate: %10.1f\n"),
+ statsp->hitrate);
+}
+
+
+static void
+print_cfg(nscd_cfg_cache_t *cfgp) {
+ (void) fprintf(stdout, gettext("\n\t CONFIG:\n"));
+ (void) fprintf(stdout, gettext("\t enabled: %s\n"),
+ yes_no(cfgp->enable));
+ (void) fprintf(stdout, gettext("\t per user cache: %s\n"),
+ yes_no(cfgp->per_user));
+ (void) fprintf(stdout, gettext("\t avoid name service: %s\n"),
+ yes_no(cfgp->avoid_ns));
+ (void) fprintf(stdout, gettext("\t check file: %s\n"),
+ yes_no(cfgp->check_files));
+ (void) fprintf(stdout, gettext("\t check file interval: %d\n"),
+ cfgp->check_interval);
+ (void) fprintf(stdout, gettext("\t positive ttl: %d\n"),
+ cfgp->pos_ttl);
+ (void) fprintf(stdout, gettext("\t negative ttl: %d\n"),
+ cfgp->neg_ttl);
+ (void) fprintf(stdout, gettext("\t keep hot count: %d\n"),
+ cfgp->keephot);
+ (void) fprintf(stdout, gettext("\t hint size: %d\n"),
+ cfgp->hint_size);
+ (void) fprintf(stdout, gettext("\t max entries: %lu%s"),
+ cfgp->maxentries,
+ cfgp->maxentries?"\n":" (unlimited)\n");
+}
+
+
+#ifdef NSCD_DEBUG
+static void
+hash_dump(nsc_db_t *nscdb, time_t now) {
+ nsc_entry_t *entry;
+ int i;
+
+ (void) fprintf(stdout, gettext("\n\nHASH TABLE:\n"));
+ for (i = 0; i < nscdb->htsize; i++) {
+ if ((entry = nscdb->htable[i]) != NULL) {
+ (void) fprintf(stdout, "hash[%d]:\n", i);
+ print_entry(nscdb, now, entry);
+ }
+ }
+}
+#endif /* NSCD_DEBUG */
+
+
+#ifdef NSCD_DEBUG
+static void
+avl_dump(nsc_db_t *nscdb, time_t now) {
+ nsc_entry_t *entry;
+ int i;
+
+ (void) fprintf(stdout, gettext("\n\nAVL TREE:\n"));
+ for (entry = avl_first(&nscdb->tree), i = 0; entry != NULL;
+ entry = avl_walk(&nscdb->tree, entry, AVL_AFTER)) {
+ (void) fprintf(stdout, "avl node[%d]:\n", i++);
+ print_entry(nscdb, now, entry);
+ }
+}
+#endif /* NSCD_DEBUG */
+
+
+#ifdef NSCD_DEBUG
+static void
+queue_dump(nsc_db_t *nscdb, time_t now) {
+ nsc_entry_t *entry;
+ int i;
+
+ (void) fprintf(stdout,
+ gettext("\n\nCACHE [name=%s, nodes=%lu]:\n"),
+ nscdb->name, avl_numnodes(&nscdb->tree));
+
+ (void) fprintf(stdout,
+ gettext("Starting with the most recently accessed:\n"));
+
+ for (entry = nscdb->qtail, i = 0; entry; entry = entry->qnext) {
+ (void) fprintf(stdout, "entry[%d]:\n", i++);
+ print_entry(nscdb, now, entry);
+ }
+}
+#endif /* NSCD_DEBUG */
+
+static void
+queue_remove(nsc_db_t *nscdb, nsc_entry_t *entry) {
+
+ if (nscdb->qtail == entry)
+ nscdb->qtail = entry->qnext;
+ else
+ entry->qprev->qnext = entry->qnext;
+
+ if (nscdb->qhead == entry)
+ nscdb->qhead = entry->qprev;
+ else
+ entry->qnext->qprev = entry->qprev;
+
+ if (nscdb->reap_node == entry)
+ nscdb->reap_node = entry->qnext;
+ entry->qnext = entry->qprev = NULL;
+}
+
+
+static void
+queue_adjust(nsc_db_t *nscdb, nsc_entry_t *entry) {
+
+#ifdef NSCD_DEBUG
+ assert(nscdb->qtail || entry->qnext == NULL &&
+ entry->qprev == NULL);
+
+ assert(nscdb->qtail && nscdb->qhead ||
+ nscdb->qtail == NULL && nscdb->qhead == NULL);
+
+ assert(entry->qprev || entry->qnext == NULL ||
+ nscdb->qtail == entry);
+#endif /* NSCD_DEBUG */
+
+ /* already in the desired position */
+ if (nscdb->qtail == entry)
+ return;
+
+ /* new queue */
+ if (nscdb->qtail == NULL) {
+ nscdb->qhead = nscdb->qtail = entry;
+ return;
+ }
+
+ /* new entry (prev == NULL AND tail != entry) */
+ if (entry->qprev == NULL) {
+ nscdb->qtail->qprev = entry;
+ entry->qnext = nscdb->qtail;
+ nscdb->qtail = entry;
+ return;
+ }
+
+ /* existing entry */
+ if (nscdb->reap_node == entry)
+ nscdb->reap_node = entry->qnext;
+ if (nscdb->qhead == entry)
+ nscdb->qhead = entry->qprev;
+ else
+ entry->qnext->qprev = entry->qprev;
+ entry->qprev->qnext = entry->qnext;
+ entry->qprev = NULL;
+ entry->qnext = nscdb->qtail;
+ nscdb->qtail->qprev = entry;
+ nscdb->qtail = entry;
+}
+
+
+/*
+ * Init cache
+ */
+nscd_rc_t
+init_cache(int debug_level) {
+ int cflags;
+
+ cflags = (debug_level > 0)?0:UMC_NODEBUG;
+ nsc_entry_cache = umem_cache_create("nsc_entry_cache",
+ sizeof (nsc_entry_t), 0, NULL, NULL, NULL,
+ NULL, NULL, cflags);
+ if (nsc_entry_cache == NULL)
+ return (NSCD_NO_MEMORY);
+ return (NSCD_SUCCESS);
+}
+
+
+/*
+ * Create cache
+ */
+nsc_db_t *
+make_cache(enum db_type dbtype, int dbop, char *name,
+ int (*compar) (const void *, const void *),
+ void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *),
+ uint_t (*gethash)(nss_XbyY_key_t *, int),
+ enum hash_type httype, int htsize) {
+
+ nsc_db_t *nscdb;
+ char *me = "make_cache";
+
+ nscdb = (nsc_db_t *)malloc(sizeof (*nscdb));
+ if (nscdb == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s: memory allocation failure\n", name);
+ goto out;
+ }
+ (void) memset(nscdb, 0, sizeof (*nscdb));
+
+ nscdb->dbop = dbop;
+ nscdb->name = name;
+ nscdb->db_type = dbtype;
+
+ /* Assign compare routine */
+ if (compar == NULL) {
+ if (_NSC_DB_CES_KEY(nscdb))
+ nscdb->compar = nsc_db_ces_key_compar;
+ else if (_NSC_DB_CIS_KEY(nscdb))
+ nscdb->compar = nsc_db_cis_key_compar;
+ else if (_NSC_DB_INT_KEY(nscdb))
+ nscdb->compar = nsc_db_int_key_compar;
+ else
+ assert(0);
+ } else {
+ nscdb->compar = compar;
+ }
+
+ /* The cache is an AVL tree */
+ avl_create(&nscdb->tree, nscdb->compar, sizeof (nsc_entry_t),
+ offsetof(nsc_entry_t, avl_link));
+
+ /* Assign log routine */
+ if (getlogstr == NULL) {
+ if (_NSC_DB_STR_KEY(nscdb))
+ nscdb->getlogstr = nsc_db_str_key_getlogstr;
+ else if (_NSC_DB_INT_KEY(nscdb))
+ nscdb->getlogstr = nsc_db_int_key_getlogstr;
+ else
+ nscdb->getlogstr = nsc_db_any_key_getlogstr;
+ } else {
+ nscdb->getlogstr = getlogstr;
+ }
+
+ /* The AVL tree based cache uses a hash table for quick access */
+ if (htsize != 0) {
+ /* Determine hash table size based on type */
+ nscdb->hash_type = httype;
+ if (htsize < 0) {
+ switch (httype) {
+ case nsc_ht_power2:
+ htsize = _NSC_INIT_HTSIZE_POWER2;
+ break;
+ case nsc_ht_prime:
+ case nsc_ht_default:
+ default:
+ htsize = _NSC_INIT_HTSIZE_PRIME;
+ }
+ }
+ nscdb->htsize = htsize;
+
+ /* Create the hash table */
+ nscdb->htable = calloc(htsize, sizeof (*(nscdb->htable)));
+ if (nscdb->htable == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s: memory allocation failure\n", name);
+ goto out;
+ }
+
+ /* Assign gethash routine */
+ if (gethash == NULL) {
+ if (_NSC_DB_CES_KEY(nscdb))
+ nscdb->gethash = nsc_db_ces_key_gethash;
+ else if (_NSC_DB_CIS_KEY(nscdb))
+ nscdb->gethash = nsc_db_cis_key_gethash;
+ else if (_NSC_DB_INT_KEY(nscdb))
+ nscdb->gethash = nsc_db_int_key_gethash;
+ else
+ assert(0);
+ } else {
+ nscdb->gethash = gethash;
+ }
+ }
+
+ (void) mutex_init(&nscdb->db_mutex, USYNC_THREAD, NULL);
+ return (nscdb);
+
+out:
+ if (nscdb->htable)
+ free(nscdb->htable);
+ if (nscdb)
+ free(nscdb);
+ return (NULL);
+}
+
+
+/*
+ * verify
+ */
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_cache_verify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * notify
+ */
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_cache_notify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+ nsc_ctx_t *ctx;
+ void *dp;
+ int i;
+
+ /* group data */
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL)) {
+ /* global config */
+ global_cfg = *(nscd_cfg_global_cache_t *)data;
+ } else if (_nscd_cfg_flag_is_set(dflag,
+ NSCD_CFG_DFLAG_SET_ALL_DB)) {
+ /* non-global config for all dbs */
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ ctx = cache_ctx_p[i];
+ if (ctx == NULL)
+ return (NSCD_CTX_NOT_FOUND);
+ (void) rw_wrlock(&ctx->cfg_rwlp);
+ ctx->cfg = *(nscd_cfg_cache_t *)data;
+ ctx->cfg_mtime = time(NULL);
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ }
+ } else {
+ /* non-global config for a specific db */
+
+ /* ignore non-caching databases */
+ if (get_cache_ctx(nswdb->name, &ctx) !=
+ NSCD_SUCCESS)
+ return (NSCD_SUCCESS);
+ (void) rw_wrlock(&ctx->cfg_rwlp);
+ ctx->cfg = *(nscd_cfg_cache_t *)data;
+ ctx->cfg_mtime = time(NULL);
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ }
+ return (NSCD_SUCCESS);
+ }
+
+ /* individual data */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL)) {
+ /* global config */
+ dp = (char *)&global_cfg + pdesc->p_offset;
+ (void) memcpy(dp, data, pdesc->p_size);
+ } else if (_nscd_cfg_flag_is_set(dflag,
+ NSCD_CFG_DFLAG_SET_ALL_DB)) {
+ /* non-global config for all dbs */
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ ctx = cache_ctx_p[i];
+ if (ctx == NULL)
+ return (NSCD_CTX_NOT_FOUND);
+ dp = (char *)&ctx->cfg + pdesc->p_offset;
+ (void) rw_wrlock(&ctx->cfg_rwlp);
+ (void) memcpy(dp, data, pdesc->p_size);
+ ctx->cfg_mtime = time(NULL);
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ }
+ } else {
+ /* non-global config for a specific db */
+
+ /* ignore non-caching databases */
+ if (get_cache_ctx(nswdb->name, &ctx) != NSCD_SUCCESS)
+ return (NSCD_SUCCESS);
+ dp = (char *)&ctx->cfg + pdesc->p_offset;
+ (void) rw_wrlock(&ctx->cfg_rwlp);
+ (void) memcpy(dp, data, pdesc->p_size);
+ ctx->cfg_mtime = time(NULL);
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ }
+ return (NSCD_SUCCESS);
+}
+
+
+/*
+ * get stat
+ */
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_cache_get_stat(
+ void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)(void *stat),
+ nscd_cfg_error_t **errorp)
+{
+ nscd_cfg_stat_cache_t *statsp, stats;
+ nsc_ctx_t *ctx;
+ int i;
+ nscd_rc_t rc;
+
+ statsp = calloc(1, sizeof (*statsp));
+ if (statsp == NULL)
+ return (NSCD_NO_MEMORY);
+
+ if (_nscd_cfg_flag_is_set(sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL)) {
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ if (cache_ctx_p[i] == NULL)
+ stats = null_stats;
+ else {
+ (void) mutex_lock(&cache_ctx_p[i]->stats_mutex);
+ stats = cache_ctx_p[i]->stats;
+ (void) mutex_unlock(
+ &cache_ctx_p[i]->stats_mutex);
+ }
+ statsp->pos_hits += stats.pos_hits;
+ statsp->neg_hits += stats.neg_hits;
+ statsp->pos_misses += stats.pos_misses;
+ statsp->neg_misses += stats.neg_misses;
+ statsp->entries += stats.entries;
+ statsp->drop_count += stats.drop_count;
+ statsp->wait_count += stats.wait_count;
+ statsp->invalidate_count +=
+ stats.invalidate_count;
+ }
+ } else {
+ if ((rc = get_cache_ctx(nswdb->name, &ctx)) != NSCD_SUCCESS) {
+ free(statsp);
+ return (rc);
+ }
+ (void) mutex_lock(&ctx->stats_mutex);
+ *statsp = ctx->stats;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ }
+
+ _NSC_GET_HITRATE(statsp);
+ *stat = statsp;
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * This function should only be called when nscd is
+ * not a daemon.
+ */
+void
+nsc_info(nsc_ctx_t *ctx, char *dbname, nscd_cfg_cache_t cfg[],
+ nscd_cfg_stat_cache_t stats[])
+{
+ int i;
+ char *me = "nsc_info";
+ nsc_ctx_t *ctx1;
+ nsc_ctx_t ctx2;
+ nscd_rc_t rc;
+
+ if (ctx) {
+ ctx_info(ctx);
+ return;
+ }
+
+ if (dbname) {
+ rc = get_cache_ctx(dbname, &ctx1);
+ if (rc == NSCD_INVALID_ARGUMENT) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: no cache context found\n", dbname);
+ return;
+ } else if (rc == NSCD_NO_MEMORY) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: unable to create cache context - no memory\n",
+ dbname);
+ return;
+ }
+ ctx_info(ctx1);
+ return;
+ }
+
+ if (cfg == NULL || stats == NULL)
+ return;
+
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+
+ ctx2.dbname = cache_name[i];
+ ctx2.cfg = cfg[i];
+ ctx2.stats = stats[i];
+ ctx_info_nolock(&ctx2);
+ }
+}
+
+static void
+ctx_info_nolock(nsc_ctx_t *ctx) {
+ nscd_cfg_cache_t cfg;
+ nscd_cfg_stat_cache_t stats;
+
+ cfg = ctx->cfg;
+ (void) fprintf(stdout, gettext("\n\nCACHE: %s\n"), ctx->dbname);
+ (void) print_cfg(&cfg);
+
+ if (cfg.enable == nscd_false)
+ return;
+
+ stats = ctx->stats;
+ (void) print_stats(&stats);
+}
+
+static void
+ctx_info(nsc_ctx_t *ctx) {
+ nscd_cfg_cache_t cfg;
+ nscd_cfg_stat_cache_t stats;
+
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ cfg = ctx->cfg;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ (void) fprintf(stdout, gettext("\n\nCACHE: %s\n"), ctx->dbname);
+ (void) print_cfg(&cfg);
+
+ if (cfg.enable == nscd_false)
+ return;
+
+ (void) mutex_lock(&ctx->stats_mutex);
+ stats = ctx->stats;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ (void) print_stats(&stats);
+}
+
+#ifdef NSCD_DEBUG
+/*
+ * This function should only be called when nscd is
+ * not a daemon.
+ */
+int
+nsc_dump(char *dbname, int dbop) {
+ nsc_ctx_t *ctx;
+ nsc_db_t *nscdb;
+ nscd_bool_t enabled;
+ time_t now;
+ char *me = "nsc_dump";
+ int i;
+
+ if ((i = get_cache_idx(dbname)) == -1) {
+ (void) fprintf(stdout, gettext("invalid cache name\n"));
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: invalid cache name\n", dbname);
+ return (NSCD_CACHE_INVALID_CACHE_NAME);
+ }
+
+ if ((ctx = cache_ctx_p[i]) == NULL) {
+ (void) fprintf(stdout, gettext("no cache context\n"));
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: no cache context\n", dbname);
+ return (NSCD_CACHE_NO_CACHE_CTX);
+ }
+
+ now = time(NULL);
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ enabled = ctx->cfg.enable;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+
+ if (enabled == nscd_false)
+ return (NSCD_CACHE_DISABLED);
+
+ nscdb = nsc_get_db(ctx, dbop);
+ if (nscdb == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s:%d: no cache found\n", dbname, dbop);
+ return (NSCD_CACHE_NO_CACHE_FOUND);
+ }
+
+ (void) mutex_lock(&nscdb->db_mutex);
+ (void) queue_dump(nscdb, now);
+ (void) hash_dump(nscdb, now);
+ (void) avl_dump(nscdb, now);
+ (void) mutex_unlock(&nscdb->db_mutex);
+ return (NSCD_SUCCESS);
+}
+#endif /* NSCD_DEBUG */
+
+/*
+ * These macros are for exclusive use of nsc_lookup
+ */
+#define NSC_LOOKUP_RETURN(retcode, loglevel, fmt) \
+ (void) mutex_unlock(&nscdb->db_mutex); \
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_##loglevel) \
+ (me, fmt, whoami); \
+ return (retcode);
+
+#define NSC_LOOKUP_NO_CACHE(str) \
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG) \
+ (me, "%s: name service lookup (bypassing cache\n", \
+ str); \
+ nss_psearch(largs->buffer, largs->bufsize); \
+ status = NSCD_GET_STATUS(largs->buffer); \
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG) \
+ (me, "%s: name service lookup status = %d\n", \
+ str, status); \
+ if (status == NSS_SUCCESS) { \
+ return (SUCCESS); \
+ } else if (status == NSS_NOTFOUND) \
+ return (NOTFOUND); \
+ else \
+ return (SERVERERROR);
+
+/*
+ * This function starts the revalidation and reaper threads
+ * for a cache
+ */
+static void
+start_threads(nsc_ctx_t *ctx) {
+
+ int errnum;
+ char *me = "start_threads";
+
+ /*
+ * kick off the revalidate thread (if necessary)
+ */
+ if (ctx->revalidate_on != nscd_true) {
+ if (thr_create(NULL, NULL, (void *(*)(void *))revalidate,
+ ctx, 0, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create (revalidate thread for %s): %s\n",
+ ctx->dbname, strerror(errnum));
+ exit(1);
+ }
+ ctx->revalidate_on = nscd_true;
+ }
+
+ /*
+ * kick off the reaper thread (if necessary)
+ */
+ if (ctx->reaper_on != nscd_true) {
+ if (thr_create(NULL, NULL, (void *(*)(void *))reaper,
+ ctx, 0, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create (reaper thread for %s): %s\n",
+ ctx->dbname, strerror(errnum));
+ exit(1);
+ }
+ ctx->reaper_on = nscd_true;
+ }
+}
+
+/*
+ * Examine the packed buffer, see if the front-end parameters
+ * indicate that the caller specified nsswitch config should be
+ * used for the lookup. Return 1 if yes, otherwise 0.
+ */
+static int
+nsw_config_in_phdr(void *buf)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buf;
+ nssuint_t off;
+ nss_dbd_t *pdbd;
+ char *me = "nsw_config_in_phdr";
+
+ off = pbuf->dbd_off;
+ if (off == 0)
+ return (0);
+ pdbd = (nss_dbd_t *)((void *)((char *)pbuf + off));
+ if (pdbd->o_default_config == 0)
+ return (0);
+
+ if ((enum nss_dbp_flags)pdbd->flags & NSS_USE_DEFAULT_CONFIG) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "use caller specified nsswitch config\n");
+ return (1);
+ } else
+ return (0);
+}
+
+static nss_status_t
+copy_result(void *rbuf, void *cbuf)
+{
+ nss_pheader_t *rphdr = (nss_pheader_t *)rbuf;
+ nss_pheader_t *cphdr = (nss_pheader_t *)cbuf;
+ char *me = "copy_result";
+
+ /* return NSS_ERROR if not enough room to copy result */
+ if (cphdr->data_len + 1 > rphdr->data_len) {
+ NSCD_SET_STATUS(rphdr, NSS_ERROR, ERANGE);
+ return (NSS_ERROR);
+ } else {
+ char *dst;
+
+ if (cphdr->data_len == 0)
+ return (NSS_SUCCESS);
+
+ dst = (char *)rphdr + rphdr->data_off;
+ (void) memcpy(dst, (char *)cphdr + cphdr->data_off,
+ cphdr->data_len);
+ rphdr->data_len = cphdr->data_len;
+ /* some frontend code expects a terminating NULL char */
+ *(dst + rphdr->data_len) = '\0';
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "cache data (len = %lld): %s\n",
+ cphdr->data_len, (char *)cphdr + cphdr->data_off);
+
+ return (NSS_SUCCESS);
+ }
+}
+
+static int
+get_dns_ttl(void *pbuf, char *dbname)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)pbuf;
+ int ttl;
+ char *me = "get_dns_ttl";
+
+ /* if returned, dns ttl is stored in the extended data area */
+ if (phdr->ext_off == 0)
+ return (-1);
+
+ if (strcmp(dbname, NSS_DBNAM_HOSTS) != 0 &&
+ strcmp(dbname, NSS_DBNAM_IPNODES) != 0)
+ return (-1);
+
+ ttl = *(nssuint_t *)((void *)((char *)pbuf + phdr->ext_off));
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "dns ttl is %d seconds\n", ttl);
+
+ return (ttl);
+}
+
+static int
+check_config(nsc_lookup_args_t *largs, nscd_cfg_cache_t *cfgp,
+ char *whoami, int flag)
+{
+ nsc_db_t *nscdb;
+ nsc_ctx_t *ctx;
+ nss_status_t status;
+ char *me = "check_config";
+
+ ctx = largs->ctx;
+ nscdb = largs->nscdb;
+
+ /* see if the cached config needs update */
+ if (nscdb->cfg_mtime != ctx->cfg_mtime) {
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ nscdb->cfg = ctx->cfg;
+ nscdb->cfg_mtime = ctx->cfg_mtime;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "config for context %s, database %s updated\n",
+ ctx->dbname, nscdb->name);
+ }
+ *cfgp = nscdb->cfg;
+
+ if (cfgp->enable == nscd_false) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: cache disabled\n", ctx->dbname);
+
+ if (UPDATEBIT & flag)
+ return (NOTFOUND);
+ else {
+ NSC_LOOKUP_NO_CACHE(whoami);
+ }
+ }
+
+ /*
+ * if caller requests lookup using his
+ * own nsswitch config, bypass cache
+ */
+ if (nsw_config_in_phdr(largs->buffer)) {
+ NSC_LOOKUP_NO_CACHE(whoami);
+ }
+
+ /* no need of cache if we are dealing with 0 ttls */
+ if (cfgp->pos_ttl <= 0 && cfgp->neg_ttl <= 0) {
+ if (flag & UPDATEBIT)
+ return (NOTFOUND);
+ else if (cfgp->avoid_ns == nscd_true)
+ return (SERVERERROR);
+ NSC_LOOKUP_NO_CACHE(whoami);
+ }
+
+ return (CONTINUE);
+}
+
+/*
+ * Invalidate cache if database file has been modified.
+ * See check_files config param for details.
+ */
+static void
+check_db_file(nsc_ctx_t *ctx, nscd_cfg_cache_t cfg,
+ char *whoami, time_t now)
+{
+ struct stat buf;
+ nscd_bool_t file_modified = nscd_false;
+ char *me = "check_db_file";
+
+ if (cfg.check_interval != 0 &&
+ (now - ctx->file_chktime) < cfg.check_interval)
+ return;
+
+ ctx->file_chktime = now;
+ if (stat(ctx->file_name, &buf) == 0) {
+ if (ctx->file_mtime == 0) {
+ (void) mutex_lock(&ctx->file_mutex);
+ if (ctx->file_mtime == 0) {
+ ctx->file_mtime = buf.st_mtime;
+ ctx->file_size = buf.st_size;
+ ctx->file_ino = buf.st_ino;
+ }
+ (void) mutex_unlock(&ctx->file_mutex);
+ } else if (ctx->file_mtime < buf.st_mtime ||
+ ctx->file_size != buf.st_size ||
+ ctx->file_ino != buf.st_ino) {
+ (void) mutex_lock(&ctx->file_mutex);
+ if (ctx->file_mtime < buf.st_mtime ||
+ ctx->file_size != buf.st_size ||
+ ctx->file_ino != buf.st_ino) {
+ file_modified = nscd_true;
+ ctx->file_mtime = buf.st_mtime;
+ ctx->file_size = buf.st_size;
+ ctx->file_ino = buf.st_ino;
+ }
+ (void) mutex_unlock(&ctx->file_mutex);
+ }
+ }
+
+ if (file_modified == nscd_true) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: file %s has been modified - invalidating cache\n",
+ whoami, ctx->file_name);
+ ctx_invalidate(ctx);
+ }
+}
+
+static int
+lookup_int(nsc_lookup_args_t *largs, int flag) {
+
+ nsc_ctx_t *ctx;
+ nsc_db_t *nscdb;
+ nscd_cfg_cache_t cfg;
+ nsc_entry_t *this_entry;
+ nsc_entry_stat_t *this_stats;
+ nsc_action_t next_action;
+ nss_status_t status;
+ nscd_bool_t delete;
+ nscd_rc_t rc;
+ char *dbname;
+ int dbop, errnum;
+ int cfg_rc;
+ nss_XbyY_args_t args;
+ char whoami[128];
+ time_t now = time(NULL); /* current time */
+ char *me = "lookup_int";
+
+ /* extract dbop, dbname, key and cred */
+ status = nss_packed_getkey(largs->buffer, largs->bufsize, &dbname,
+ &dbop, &args);
+ if (status != NSS_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "nss_packed_getkey failure (%d)\n", status);
+ return (SERVERERROR);
+ }
+
+ /* get the cache context */
+ if (largs->ctx == NULL) {
+ if (get_cache_ctx(dbname, &largs->ctx) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: no cache context found\n", dbname);
+
+ if (UPDATEBIT & flag)
+ return (NOTFOUND);
+ else {
+ NSC_LOOKUP_NO_CACHE(dbname);
+ }
+ }
+ }
+ ctx = largs->ctx;
+
+ if (largs->nscdb == NULL) {
+ if ((largs->nscdb = nsc_get_db(ctx, dbop)) == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s:%d: no cache found\n",
+ dbname, dbop);
+
+ if (UPDATEBIT & flag)
+ return (NOTFOUND);
+ else {
+ NSC_LOOKUP_NO_CACHE(dbname);
+ }
+ }
+ }
+
+ nscdb = largs->nscdb;
+
+ _NSCD_LOG_IF(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ALL) {
+ (void) nscdb->getlogstr(nscdb->name, whoami,
+ sizeof (whoami), &args);
+ }
+
+ if (UPDATEBIT & flag) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: refresh start\n", whoami);
+ } else {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: lookup start\n", whoami);
+ }
+
+ cfg_rc = check_config(largs, &cfg, whoami, flag);
+ if (cfg_rc != CONTINUE)
+ return (cfg_rc);
+
+ /*
+ * Invalidate cache if file has been modified.
+ */
+ if (cfg.check_files == nscd_true)
+ check_db_file(ctx, cfg, whoami, now);
+
+ (void) mutex_lock(&nscdb->db_mutex);
+
+ /* Lookup the cache table */
+ for (;;) {
+ delete = nscd_false;
+ rc = lookup_cache(largs, &cfg, &args, whoami, &this_entry);
+ if (rc != NSCD_SUCCESS) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+
+ /* Either no entry and avoid name service */
+ if (rc == NSCD_DB_ENTRY_NOT_FOUND ||
+ rc == NSCD_INVALID_ARGUMENT)
+ return (NOTFOUND);
+
+ /* OR memory error */
+ return (SERVERERROR);
+ }
+
+ /* get the stats from the entry */
+ this_stats = &this_entry->stats;
+
+ /*
+ * What should we do next ?
+ */
+ switch (this_stats->status) {
+ case ST_NEW_ENTRY:
+ delete = nscd_true;
+ next_action = _NSC_NSLOOKUP;
+ break;
+ case ST_UPDATE_PENDING:
+ if (flag & UPDATEBIT) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ return (NOTFOUND);
+ } else if (this_stats->timestamp < now)
+ next_action = _NSC_WAIT;
+ else
+ next_action = _NSC_USECACHED;
+ break;
+ case ST_LOOKUP_PENDING:
+ if (flag & UPDATEBIT) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ return (NOTFOUND);
+ }
+ next_action = _NSC_WAIT;
+ break;
+ case ST_DISCARD:
+ if (cfg.avoid_ns == nscd_true) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ return (NOTFOUND);
+ }
+ /* otherwise reuse the entry */
+ (void) memset(this_stats, 0, sizeof (*this_stats));
+ next_action = _NSC_NSLOOKUP;
+ break;
+ default:
+ if (cfg.avoid_ns == nscd_true)
+ next_action = _NSC_USECACHED;
+ else if ((flag & UPDATEBIT) ||
+ (this_stats->timestamp < now)) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: cached entry needs to be updated\n",
+ whoami);
+ next_action = _NSC_NSLOOKUP;
+ } else
+ next_action = _NSC_USECACHED;
+ break;
+ }
+
+ if (next_action == _NSC_WAIT) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: need to wait\n", whoami);
+
+ /* do we have clearance ? */
+ if (_nscd_get_clearance(&ctx->throttle_sema) != 0) {
+ /* nope. quit */
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.drop_count++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ NSC_LOOKUP_RETURN(NOSERVER, WARNING,
+ "%s: no clearance to wait\n");
+ }
+ /* yes can wait */
+ (void) nscd_wait(&ctx->wait, &nscdb->db_mutex,
+ &this_stats->status);
+ (void) _nscd_release_clearance(&ctx->throttle_sema);
+ continue;
+ }
+
+ break;
+ }
+
+
+ if (!(UPDATEBIT & flag))
+ this_stats->hits++; /* update hit count */
+
+ if (next_action == _NSC_NSLOOKUP) {
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: name service lookup required\n", whoami);
+
+ if (_nscd_get_clearance(&ctx->throttle_sema) != 0) {
+ if (delete == nscd_true)
+ delete_entry(nscdb, ctx, this_entry);
+ else
+ this_stats->status = ST_DISCARD;
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.drop_count++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ NSC_LOOKUP_RETURN(NOSERVER, WARNING,
+ "%s: no clearance for lookup\n");
+ }
+
+ /* block any threads accessing this entry */
+ this_stats->status = (flag & UPDATEBIT)?
+ ST_UPDATE_PENDING:ST_LOOKUP_PENDING;
+
+ /* release lock and do name service lookup */
+ (void) mutex_unlock(&nscdb->db_mutex);
+ nss_psearch(largs->buffer, largs->bufsize);
+ status = NSCD_GET_STATUS(largs->buffer);
+ (void) mutex_lock(&nscdb->db_mutex);
+ this_stats->status = 0;
+ (void) _nscd_release_clearance(&ctx->throttle_sema);
+
+ /* signal waiting threads */
+ (void) nscd_signal(&ctx->wait, &this_stats->status);
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: name service lookup status = %d\n",
+ whoami, status);
+
+ if (status == NSS_SUCCESS) {
+ int ttl;
+
+ /*
+ * data found in name service
+ * update cache
+ */
+ status = dup_packed_buffer(largs, this_entry);
+ if (status != NSS_SUCCESS) {
+ delete_entry(nscdb, ctx, this_entry);
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: failed to update cache\n");
+ }
+
+ /*
+ * store unpacked key in cache
+ */
+ status = nss_packed_getkey(this_entry->buffer,
+ this_entry->bufsize,
+ &dbname, &dbop, &args);
+ if (status != NSS_SUCCESS) {
+ delete_entry(nscdb, ctx, this_entry);
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: failed to extract key\n");
+ }
+ this_entry->key = args.key; /* struct copy */
+
+ /* update +ve miss count */
+ if (!(UPDATEBIT & flag)) {
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.pos_misses++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ }
+
+ /* update +ve ttl */
+ ttl = get_dns_ttl(largs->buffer, dbname);
+ /* honor the dns ttl less than postive ttl */
+ if (ttl < 0 || ttl > cfg.pos_ttl)
+ ttl = cfg.pos_ttl;
+ this_stats->timestamp = time(NULL) + ttl;
+
+ /*
+ * start the revalidation and reaper threads
+ * if not already started
+ */
+ start_threads(ctx);
+
+ NSC_LOOKUP_RETURN(SUCCESS, DEBUG,
+ "%s: cache updated with positive entry\n");
+ } else if (status == NSS_NOTFOUND) {
+ /*
+ * data not found in name service
+ * update cache
+ */
+
+ if (NSCD_GET_ERRNO(largs->buffer) == ERANGE) {
+ delete_entry(nscdb, ctx, this_entry);
+ NSC_LOOKUP_RETURN(NOTFOUND, DEBUG,
+ "%s: ERANGE, cache not updated with negative entry\n");
+ }
+
+ status = dup_packed_buffer(largs, this_entry);
+ if (status != NSS_SUCCESS) {
+ delete_entry(nscdb, ctx, this_entry);
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: failed to update cache\n");
+ }
+
+ /* store unpacked key in cache */
+ status = nss_packed_getkey(this_entry->buffer,
+ this_entry->bufsize,
+ &dbname, &dbop, &args);
+ if (status != NSS_SUCCESS) {
+ delete_entry(nscdb, ctx, this_entry);
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: failed to extract key\n");
+ }
+ this_entry->key = args.key; /* struct copy */
+
+ /* update -ve ttl */
+ this_stats->timestamp = time(NULL) + cfg.neg_ttl;
+
+ /* update -ve miss count */
+ if (!(UPDATEBIT & flag)) {
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.neg_misses++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+ }
+
+ /*
+ * start the revalidation and reaper threads
+ * if not already started
+ */
+ start_threads(ctx);
+
+ NSC_LOOKUP_RETURN(NOTFOUND, DEBUG,
+ "%s: cache updated with negative entry\n");
+ } else {
+ /*
+ * name service lookup failed
+ */
+ errnum = NSCD_GET_ERRNO(largs->buffer);
+ if (delete == nscd_true)
+ delete_entry(nscdb, ctx, this_entry);
+ else
+ this_stats->status = ST_DISCARD;
+
+ (void) mutex_unlock(&nscdb->db_mutex);
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: name service lookup failed (status=%d, errno=%d)\n",
+ whoami, status, errnum);
+
+ return (SERVERERROR);
+ }
+ } else if (next_action == _NSC_USECACHED) {
+ /*
+ * found entry in cache
+ */
+ if (UPDATEBIT & flag) {
+ NSC_LOOKUP_RETURN(SUCCESS, DEBUG,
+ "%s: no need to update\n");
+ }
+
+ if (NSCD_GET_STATUS((nss_pheader_t *)this_entry->buffer) ==
+ NSS_SUCCESS) {
+ /* positive hit */
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.pos_hits++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+
+ /* update response buffer */
+ if (copy_result(largs->buffer,
+ this_entry->buffer) != NSS_SUCCESS) {
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: response buffer insufficient\n");
+ }
+
+ NSC_LOOKUP_RETURN(SUCCESS, DEBUG,
+ "%s: positive entry in cache\n");
+ } else {
+ /* negative hit */
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.neg_hits++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+
+ NSCD_SET_STATUS((nss_pheader_t *)largs->buffer,
+ NSCD_GET_STATUS(this_entry->buffer),
+ NSCD_GET_ERRNO(this_entry->buffer));
+ NSCD_SET_HERRNO((nss_pheader_t *)largs->buffer,
+ NSCD_GET_HERRNO(this_entry->buffer));
+
+ NSC_LOOKUP_RETURN(NOTFOUND, DEBUG,
+ "%s: negative entry in cache\n");
+ }
+ }
+
+ NSC_LOOKUP_RETURN(SERVERERROR, ERROR,
+ "%s: cache backend failure\n");
+}
+
+/*
+ * NSCD cache backend lookup function
+ */
+/*ARGSUSED*/
+void
+nsc_lookup(nsc_lookup_args_t *largs, int flag) {
+
+ nss_pheader_t *phdr = (nss_pheader_t *)largs->buffer;
+ int rc;
+
+ rc = lookup_int(largs, 0);
+
+ if (NSCD_GET_STATUS(phdr) == NSS_TRYLOCAL)
+ return;
+
+ switch (rc) {
+
+ case SUCCESS:
+ NSCD_RETURN_STATUS(phdr, NSS_SUCCESS, 0);
+ break;
+
+ case NOTFOUND:
+ NSCD_RETURN_STATUS(phdr, NSS_NOTFOUND, -1);
+ break;
+
+ case SERVERERROR:
+ /* status and errno already set in the phdr */
+ break;
+
+ case NOSERVER:
+ NSCD_RETURN_STATUS(phdr, NSS_UNAVAIL, -1);
+ break;
+ }
+}
+
+
+static nsc_ctx_t *
+init_cache_ctx(int i) {
+ nsc_ctx_t *ctx;
+
+ ctx = calloc(1, sizeof (nsc_ctx_t));
+ if (ctx == NULL)
+ return (NULL);
+
+ /* init locks and semaphores */
+ (void) mutex_init(&ctx->file_mutex, USYNC_THREAD, NULL);
+ (void) rwlock_init(&ctx->cfg_rwlp, USYNC_THREAD, NULL);
+ (void) mutex_init(&ctx->stats_mutex, USYNC_THREAD, NULL);
+ (void) _nscd_init_cache_sema(&ctx->throttle_sema, cache_name[i]);
+ cache_init_ctx[i](ctx);
+ cache_ctx_p[i] = ctx;
+
+ return (ctx);
+}
+
+
+static void
+revalidate(nsc_ctx_t *ctx)
+{
+ for (;;) {
+ int i, slp, interval, count;
+
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ slp = ctx->cfg.pos_ttl;
+ count = ctx->cfg.keephot;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+
+ if (slp < 60)
+ slp = 60;
+ if (count != 0) {
+ interval = (slp/2)/count;
+ if (interval == 0)
+ interval = 1;
+ (void) sleep(slp*2/3);
+ for (i = 0; i < ctx->db_count; i++) {
+ getxy_keepalive(ctx, ctx->nsc_db[i],
+ count, interval);
+ }
+ } else {
+ (void) sleep(slp);
+ }
+ }
+}
+
+
+static void
+getxy_keepalive(nsc_ctx_t *ctx, nsc_db_t *nscdb, int keep, int interval)
+{
+ nsc_keephot_t *table;
+ nsc_entry_t *entry, *ptr;
+ int i;
+ nsc_lookup_args_t *largs;
+ nss_pheader_t *phdr;
+ int bufsiz;
+ char *me = "getxy_keepalive";
+
+ /* we won't be here if keep == 0 so need to check that */
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: keep alive\n", nscdb->name);
+
+ if ((table = maken(keep)) == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "memory allocation failure\n");
+ exit(1);
+ }
+
+ (void) mutex_lock(&nscdb->db_mutex);
+ entry = nscdb->qtail;
+ while (entry != NULL) {
+ /* leave pending calls alone */
+ if (!(entry->stats.status & ST_PENDING)) {
+ /* do_revalidate */
+ (void) insertn(table, entry->stats.hits,
+ entry);
+ }
+ entry = entry->qnext;
+ }
+ for (i = 1; i <= keep; i++) {
+ if (table[i].ptr == NULL)
+ continue;
+ ptr = (nsc_entry_t *)table[i].ptr;
+ phdr = (nss_pheader_t *)ptr->buffer;
+ if (NSCD_GET_STATUS(phdr) == NSS_SUCCESS)
+ /*
+ * for positive cache, in addition to the packed
+ * header size, allocate twice the size of the
+ * existing result (in case the result grows
+ * larger)
+ */
+ bufsiz = phdr->data_off + 2 * phdr->data_len;
+ else
+ /*
+ * for negative cache, allocate 8K buffer to
+ * hold result in case the next lookup may
+ * return something (in addition to the
+ * packed header size)
+ */
+ bufsiz = phdr->data_off + 8096;
+ table[i].ptr = malloc(bufsiz);
+ if (table[i].ptr == NULL) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "memory allocation failure\n");
+ exit(1);
+ }
+ (void) memcpy(table[i].ptr, ptr->buffer, ptr->bufsize);
+ ((nss_pheader_t *)table[i].ptr)->pbufsiz = bufsiz;
+ table[i].num = bufsiz;
+ }
+ (void) mutex_unlock(&nscdb->db_mutex);
+
+ /* launch update thread for each keep hot entry */
+ for (i = keep; i > 0; i--) {
+ if (table[i].ptr == NULL)
+ continue; /* unused slot in table */
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: launching update\n", nscdb->name);
+ largs = (nsc_lookup_args_t *)malloc(sizeof (*largs));
+ if (largs == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "memory allocation failure\n");
+ exit(1);
+ }
+ largs->buffer = table[i].ptr;
+ largs->bufsize = table[i].num;
+ largs->ctx = ctx;
+ largs->nscdb = nscdb;
+ if (launch_update(largs) < 0)
+ exit(1);
+ (void) sleep(interval);
+ }
+
+ /*
+ * The update thread will handle freeing of buffer and largs.
+ * Free the table here.
+ */
+ free(table);
+}
+
+
+static int
+launch_update(nsc_lookup_args_t *in)
+{
+ char *me = "launch_update";
+ int errnum;
+
+ errnum = thr_create(NULL, NULL, (void *(*)(void*))do_update,
+ in, 0|THR_DETACHED, NULL);
+ if (errnum != 0) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s: thread creation failure (%d)\n",
+ in->nscdb->name, errnum);
+ return (-1);
+ }
+ return (0);
+}
+
+
+static void
+do_update(nsc_lookup_args_t *in) {
+ nss_pheader_t *phdr = (nss_pheader_t *)in->buffer;
+
+ /* update the length of the data buffer */
+ phdr->data_len = phdr->pbufsiz - phdr->data_off;
+
+ (void) lookup_int(in, UPDATEBIT);
+ if (in->buffer)
+ free(in->buffer);
+ free(in);
+}
+
+
+/*
+ * Invalidate cache
+ */
+void
+nsc_invalidate(nsc_ctx_t *ctx, char *dbname, nsc_ctx_t **ctxs) {
+ int i;
+ char *me = "nsc_invalidate";
+
+ if (ctx) {
+ ctx_invalidate(ctx);
+ return;
+ }
+
+ if (dbname) {
+ if ((i = get_cache_idx(dbname)) == -1) {
+ _NSCD_LOG(NSCD_LOG_CACHE,
+ NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: invalid cache name\n", dbname);
+ return;
+ }
+ if ((ctx = cache_ctx_p[i]) == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE,
+ NSCD_LOG_LEVEL_WARNING)
+ (me, "%s: no cache context found\n",
+ dbname);
+ return;
+ }
+ ctx_invalidate(ctx);
+ return;
+ }
+
+ if (ctxs == NULL)
+ ctxs = cache_ctx_p;
+
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ if (ctxs[i] != NULL)
+ ctx_invalidate(ctxs[i]);
+ }
+}
+
+
+/*
+ * Invalidate cache by context
+ */
+static void
+ctx_invalidate(nsc_ctx_t *ctx) {
+ int i;
+ nsc_entry_t *entry;
+ char *me = "ctx_invalidate";
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: invalidate cache\n", ctx->dbname);
+
+ for (i = 0; i < ctx->db_count; i++) {
+ if (ctx->nsc_db[i] == NULL)
+ continue;
+ (void) mutex_lock(&ctx->nsc_db[i]->db_mutex);
+ entry = ctx->nsc_db[i]->qtail;
+ while (entry != NULL) {
+ /* leave pending calls alone */
+ if (!(entry->stats.status & ST_PENDING))
+ entry->stats.status = ST_DISCARD;
+ entry = entry->qnext;
+ }
+ (void) mutex_unlock(&ctx->nsc_db[i]->db_mutex);
+ }
+
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.invalidate_count++;
+ (void) mutex_unlock(&ctx->stats_mutex);
+}
+
+
+/*
+ * Free nsc_entry_t
+ *
+ * Pre-reqs:
+ * nscdb->db_mutex lock must be held before calling this function
+ */
+static void
+delete_entry(nsc_db_t *nscdb, nsc_ctx_t *ctx, nsc_entry_t *entry) {
+ uint_t hash;
+
+ avl_remove(&nscdb->tree, entry);
+ HASH_REMOVE(nscdb, entry, hash, nscd_false);
+ queue_remove(nscdb, entry);
+ if (entry->buffer != NULL) {
+ free(entry->buffer);
+ entry->buffer = NULL;
+ }
+ umem_cache_free(nsc_entry_cache, entry);
+ (void) mutex_lock(&ctx->stats_mutex);
+ ctx->stats.entries--;
+ (void) mutex_unlock(&ctx->stats_mutex);
+}
+
+
+static nscd_rc_t
+lookup_cache(nsc_lookup_args_t *largs, nscd_cfg_cache_t *cfgp,
+ nss_XbyY_args_t *argp, char *whoami, nsc_entry_t **entry) {
+
+ nsc_db_t *nscdb;
+ nsc_ctx_t *ctx;
+ uint_t hash;
+ avl_index_t pos;
+ ulong_t nentries;
+ nsc_entry_t find_entry, *node;
+ char *me = "lookup_cache";
+
+ ctx = largs->ctx;
+ nscdb = largs->nscdb;
+
+ /* set the search key */
+ find_entry.key = argp->key; /* struct copy (not deep) */
+
+ /* lookup the hash table ==> O(1) */
+ if (nscdb->htable) {
+ *entry = hash_find(nscdb, &find_entry, &hash, nscd_true);
+ if (*entry != NULL) {
+ (void) queue_adjust(nscdb, *entry);
+ return (NSCD_SUCCESS);
+ }
+ }
+
+ /* if not found, lookup the AVL tree ==> O(log n) */
+ *entry = (nsc_entry_t *)avl_find(&nscdb->tree, &find_entry, &pos);
+ if (*entry != NULL) {
+ (void) queue_adjust(nscdb, *entry);
+ /* move it to the hash table */
+ if (nscdb->htable) {
+ if (nscdb->htable[hash] == NULL ||
+ (*entry)->stats.hits >=
+ nscdb->htable[hash]->stats.hits) {
+ nscdb->htable[hash] = *entry;
+ }
+ }
+ return (NSCD_SUCCESS);
+ }
+
+ /* entry not found in the cache */
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: cache miss\n", whoami);
+
+ if (cfgp->avoid_ns == nscd_true) {
+ _NSCD_LOG(NSCD_LOG_CACHE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: avoid name service\n", whoami);
+ return (NSCD_DB_ENTRY_NOT_FOUND);
+ }
+
+ /* allocate memory for new entry (stub) */
+ *entry = (nsc_entry_t *)umem_cache_alloc(nsc_entry_cache,
+ UMEM_DEFAULT);
+ if (*entry == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "%s: memory allocation failure\n", whoami);
+ return (NSCD_NO_MEMORY);
+ }
+ (void) memset(*entry, 0, sizeof (**entry));
+
+ /*
+ * Note that the actual data for the key is stored within
+ * the largs->buffer (input buffer to nsc_lookup).
+ * find_entry.key only contains pointers to this data.
+ *
+ * If largs->buffer will be re-allocated by nss_psearch
+ * then (*entry)->key will have dangling pointers.
+ * In such case, the following assignment needs to be
+ * replaced by code that duplicates the key.
+ */
+ (*entry)->key = find_entry.key;
+
+ /*
+ * Add the entry to the cache.
+ */
+ avl_insert(&nscdb->tree, *entry, pos); /* O(log n) */
+ (void) queue_adjust(nscdb, *entry); /* constant */
+ if (nscdb->htable) /* constant */
+ nscdb->htable[hash] = *entry;
+ (*entry)->stats.status = ST_NEW_ENTRY;
+
+ (void) mutex_lock(&ctx->stats_mutex);
+ nentries = ++(ctx->stats.entries);
+ (void) mutex_unlock(&ctx->stats_mutex);
+
+ /* Have we exceeded max entries ? */
+ if (cfgp->maxentries > 0 && nentries > cfgp->maxentries) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: maximum entries exceeded -- "
+ "deleting least recently used entry\n",
+ whoami);
+
+ node = nscdb->qhead;
+ while (node != NULL && node != *entry) {
+ if (node->stats.status == ST_DISCARD ||
+ !(node->stats.status & ST_PENDING)) {
+ delete_entry(nscdb, ctx, node);
+ break;
+ }
+ node = node->qprev;
+ }
+
+ /*
+ * It's okay if we were not able to find one to delete.
+ * The reaper (when invoked) will return the cache to a
+ * safe level.
+ */
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static void
+reaper(nsc_ctx_t *ctx) {
+ uint_t ttl, extra_sleep, total_sleep, intervals;
+ uint_t nodes_per_interval, seconds_per_interval;
+ ulong_t nsc_entries;
+ char *me = "reaper";
+
+ for (;;) {
+ (void) mutex_lock(&ctx->stats_mutex);
+ nsc_entries = ctx->stats.entries;
+ (void) mutex_unlock(&ctx->stats_mutex);
+
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ ttl = ctx->cfg.pos_ttl;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+
+ if (nsc_entries == 0) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: nothing to reap\n", ctx->dbname);
+
+ /* sleep for atleast 60 seconds */
+ if (ttl < 60)
+ ttl = 60;
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: sleep %d\n", ctx->dbname, ttl);
+ (void) sleep(ttl);
+ continue;
+ }
+
+ if (ttl < 32) ttl = 32;
+ if (ttl > (1<<28)) ttl = 1<<28;
+
+ /*
+ * minimum nodes_per_interval = 256 or 1<<8
+ * maximum nodes_per_interval = nsc_entries
+ * minimum seconds_per_interval = 32 or 1<<5
+ * maximum_seconds_per_interval = ttl
+ */
+ if (nsc_entries <= ttl) {
+ intervals = (nsc_entries >> 8) + 1;
+ seconds_per_interval = ttl / intervals;
+ nodes_per_interval = 256;
+ } else {
+ intervals = (ttl >> 5) + 1;
+ seconds_per_interval = 32;
+ nodes_per_interval = nsc_entries / intervals;
+ if (nodes_per_interval < 256)
+ nodes_per_interval = 256;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: total entries = %d, "
+ "seconds per interval = %d, "
+ "nodes per interval = %d\n",
+ ctx->dbname, nsc_entries, seconds_per_interval,
+ nodes_per_interval);
+ total_sleep = reap_cache(ctx, nodes_per_interval,
+ seconds_per_interval);
+ extra_sleep = 1 + ttl - total_sleep;
+ if (extra_sleep > 0)
+ (void) sleep(extra_sleep);
+ }
+}
+
+
+static uint_t
+reap_cache(nsc_ctx_t *ctx, uint_t nodes_per_interval,
+ uint_t seconds_per_interval) {
+ uint_t nodes_togo, total_sleep;
+ time_t now;
+ nsc_entry_t *node, *next_node;
+ nsc_db_t *nscdb;
+ uint_t primes[] = {_NSC_HTSIZE_PRIMES};
+ ulong_t count, nentries, maxentries;
+ int i, slot, value, newhtsize;
+ char *me = "reap_cache";
+
+ count = 0;
+ total_sleep = 0;
+ nodes_togo = nodes_per_interval;
+ now = time(NULL);
+
+ for (i = 0; i < ctx->db_count; i++) {
+ nscdb = ctx->nsc_db[i];
+ (void) mutex_lock(&nscdb->db_mutex);
+ nscdb->reap_node = nscdb->qtail;
+ while (nscdb->reap_node != NULL) {
+ if (nodes_togo == 0) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ (void) sleep(seconds_per_interval);
+ total_sleep += seconds_per_interval;
+ nodes_togo = nodes_per_interval;
+ now = time(NULL);
+ (void) mutex_lock(&nscdb->db_mutex);
+ }
+ /* delete ST_DISCARD and expired nodes */
+ if ((node = nscdb->reap_node) == NULL)
+ break;
+ if (node->stats.status == ST_DISCARD ||
+ (!(node->stats.status & ST_PENDING) &&
+ node->stats.timestamp < now)) {
+ /*
+ * Delete entry if its discard flag is
+ * set OR if it has expired. Entries
+ * with pending updates are not
+ * deleted.
+ * nscdb->reap_node will be adjusted
+ * by delete_entry()
+ */
+ delete_entry(nscdb, ctx, node);
+ count++;
+ } else {
+ nscdb->reap_node = node->qnext;
+ }
+ nodes_togo--;
+ }
+
+ if (nscdb->htsize == 0) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ continue;
+ }
+
+ /*
+ * Dynamic adjustment of hash table size.
+ *
+ * Hash table size is roughly 1/8th of the
+ * total entries. However the size is changed
+ * only when the number of entries double or
+ * reduced by half
+ */
+ nentries = avl_numnodes(&nscdb->tree);
+ for (slot = 0, value = _NSC_INIT_HTSIZE_SLOT_VALUE;
+ slot < _NSC_HTSIZE_NUM_SLOTS && nentries > value;
+ value = (value << 1) + 1, slot++);
+ if (nscdb->hash_type == nsc_ht_power2)
+ newhtsize = _NSC_INIT_HTSIZE_POWER2 << slot;
+ else
+ newhtsize = primes[slot];
+
+ /* Recommended size is same as the current size. Done */
+ if (nscdb->htsize == newhtsize) {
+ (void) mutex_unlock(&nscdb->db_mutex);
+ continue;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: resizing hash table from %d to %d\n",
+ nscdb->name, nscdb->htsize, newhtsize);
+
+ /*
+ * Dump old hashes because it would be time
+ * consuming to rehash them.
+ */
+ (void) free(nscdb->htable);
+ nscdb->htable = calloc(newhtsize, sizeof (*(nscdb->htable)));
+ if (nscdb->htable == NULL) {
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_ERROR)
+ (me,
+ "%s: memory allocation failure\n",
+ nscdb->name);
+ /* -1 to try later */
+ nscdb->htsize = -1;
+ } else {
+ nscdb->htsize = newhtsize;
+ }
+ (void) mutex_unlock(&nscdb->db_mutex);
+ }
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: reaped %lu entries\n", ctx->dbname, count);
+
+ /*
+ * if cache is almost full then reduce it to a safe level by
+ * evicting LRU entries
+ */
+
+ (void) rw_rdlock(&ctx->cfg_rwlp);
+ maxentries = ctx->cfg.maxentries;
+ (void) rw_unlock(&ctx->cfg_rwlp);
+
+ /* No limit on number of entries. Done */
+ if (maxentries == 0)
+ goto out;
+
+ (void) mutex_lock(&ctx->stats_mutex);
+ nentries = ctx->stats.entries;
+ (void) mutex_unlock(&ctx->stats_mutex);
+
+ /* what is the percentage of cache used ? */
+ value = (nentries * 100) / maxentries;
+ if (value < _NSC_EVICTION_START_LEVEL)
+ goto out;
+
+ /*
+ * cache needs to be reduced to a safe level
+ */
+ value -= _NSC_EVICTION_SAFE_LEVEL;
+ for (i = 0, count = 0; i < ctx->db_count; i++) {
+ /*
+ * Reduce each subcache by 'value' percent
+ */
+ nscdb = ctx->nsc_db[i];
+ (void) mutex_lock(&nscdb->db_mutex);
+ nodes_togo = (value * avl_numnodes(&nscdb->tree)) / 100;
+
+ /* Start from LRU entry i.e queue head */
+ next_node = nscdb->qhead;
+ while (nodes_togo > 0 && next_node != NULL) {
+ node = next_node;
+ next_node = next_node->qprev;
+ if (node->stats.status == ST_DISCARD ||
+ !(node->stats.status & ST_PENDING)) {
+ /* Leave nodes with pending updates alone */
+ delete_entry(nscdb, ctx, node);
+ count++;
+ nodes_togo--;
+ }
+ }
+ (void) mutex_unlock(&nscdb->db_mutex);
+ }
+
+ _NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: evicted %lu LRU entries\n", ctx->dbname, count);
+
+out:
+ return (total_sleep);
+}
diff --git a/usr/src/cmd/nscd/cache.h b/usr/src/cmd/nscd/cache.h
new file mode 100644
index 0000000000..088e8e1512
--- /dev/null
+++ b/usr/src/cmd/nscd/cache.h
@@ -0,0 +1,372 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_H
+#define _NSCD_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This is a private header file. Applications should not directly include
+ * this file.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/avl.h>
+#include <thread.h>
+#include <synch.h>
+#include <nss_dbdefs.h>
+#include "getxby_door.h"
+#include "nscd_common.h"
+#include "nscd_config.h"
+
+/*
+ * OR'D in by server to call self for updates
+ */
+#define UPDATEBIT (1<<30)
+#define MASKUPDATEBIT(a) ((~UPDATEBIT)&(a))
+
+/*
+ * debug levels
+ */
+#define DBG_OFF 0
+#define DBG_CANT_FIND 2
+#define DBG_NETLOOKUPS 4
+#define DBG_ALL 6
+
+/*
+ * Max size name we allow to be passed to avoid
+ * buffer overflow problems
+ */
+#define NSCDMAXNAMELEN 255
+
+/*
+ * cached entry status
+ */
+#define ST_UPDATE_PENDING 0x1
+#define ST_LOOKUP_PENDING 0x2
+#define ST_PENDING (ST_LOOKUP_PENDING | ST_UPDATE_PENDING)
+#define ST_NEW_ENTRY 0x4
+#define ST_DISCARD 0x8
+
+/*
+ * Cache eviction start and stop levels
+ */
+#define _NSC_EVICTION_START_LEVEL 90
+#define _NSC_EVICTION_SAFE_LEVEL 80
+
+/*
+ * other internal constants
+ */
+#define _NSC_MAX_DB 2
+#define _NSC_PUBLIC_ACCESS -1
+#define _NSC_FILE_CHECK_TIME 0 /* check always for backwards compat */
+
+/*
+ * Macros used for logging purposes
+ */
+#define yes_no(flag) (flag == nscd_true)?"yes":"no"
+#define check_null(str) (str)?str:"<null>"
+
+/*
+ * Macros used by compare routines
+ */
+#define _NSC_INT_KEY_CMP(n1, n2) \
+ (n1 > n2)?1:((n1 == n2)?0:-1)
+
+#define _NSC_GET_HITRATE(sp) \
+ sp->hitrate = sp->pos_misses + sp->neg_misses + \
+ sp->pos_hits + sp->neg_hits; \
+ if (sp->hitrate > 0.0) \
+ sp->hitrate = (100.0 * \
+ ((double)sp->pos_hits + \
+ (double)sp->neg_hits)) / sp->hitrate;
+
+/*
+ * nsc_lookup action
+ */
+typedef enum {
+ _NSC_NSLOOKUP = 0,
+ _NSC_WAIT,
+ _NSC_USECACHED
+} nsc_action_t;
+
+/*
+ * Structure to handle waiting for pending name service requests
+ */
+typedef struct waiter {
+ cond_t w_waitcv;
+ uint8_t *w_key;
+ struct waiter *w_next, *w_prev;
+} waiter_t;
+
+/*
+ * What each entry in the nameserver cache looks like.
+ */
+
+typedef struct nsc_entry_stat {
+ uint_t hits; /* number of hits */
+ uint8_t status; /* activity status */
+ time_t timestamp; /* expiry time */
+ int refcount; /* reference count */
+} nsc_entry_stat_t;
+
+typedef struct nsc_entry {
+ avl_node_t avl_link; /* libavl requirement */
+ struct nsc_entry *qnext; /* next on pqueue */
+ struct nsc_entry *qprev; /* prev on pqueue */
+ nsc_entry_stat_t stats; /* entry's statistics */
+ nss_XbyY_key_t key; /* entry's key */
+ void *buffer; /* data buffer */
+ size_t bufsize; /* data buffer length */
+} nsc_entry_t;
+
+typedef struct nsc_keephot {
+ void *ptr;
+ uint_t num;
+} nsc_keephot_t;
+
+/*
+ * Macros used by hash table
+ *
+ * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table
+ * sizes when hash table type is nsc_ht_prime. For hash tables of
+ * type nsc_ht_power2, the size is automatically calculated.
+ * Number of primes listed below is _NSC_HTSIZE_NUM_SLOTS + 1.
+ * Each number (except the first) is a prime closest to a
+ * power of 2 in increasing order. Ex: 509 is the closest prime to
+ * 512 (2**9), 1021 is closest to 1024 (2**10), and so on.
+ * The first prime is chosen as 211 for historical reasons.
+ */
+#define _NSC_INIT_HTSIZE_PRIME 211
+#define _NSC_INIT_HTSIZE_POWER2 256
+#define _NSC_INIT_HTSIZE_SLOT_VALUE 2896
+#define _NSC_HTSIZE_NUM_SLOTS 10
+#define _NSC_HTSIZE_PRIMES 211, 509, 1021, 2053, 4099, 8191, \
+ 16381, 32771, 65537, 131071, 262147
+
+#define _NSC_DB_CES_KEY(ptr) \
+ ((ptr)->db_type == nsc_key_ces)
+#define _NSC_DB_CIS_KEY(ptr) \
+ ((ptr)->db_type == nsc_key_cis)
+#define _NSC_DB_STR_KEY(ptr) \
+ _NSC_DB_CES_KEY(ptr) || _NSC_DB_CIS_KEY(ptr)
+#define _NSC_DB_INT_KEY(ptr) \
+ ((ptr)->db_type == nsc_key_int)
+
+/*
+ * cache backend param group (global)
+ */
+#define NSCD_CFG_GROUP_INFO_GLOBAL_CACHE {1, 0x0001}
+typedef struct nscd_cfg_global_cache {
+ nscd_cfg_group_info_t gi; /* config requirement */
+ nscd_bool_t enable;
+} nscd_cfg_global_cache_t;
+
+#define NSCD_CFG_GLOBAL_CACHE_DEFAULTS \
+ { NSCD_CFG_GROUP_INFO_GLOBAL_CACHE, nscd_true }
+
+/*
+ * cache backend param group (per database)
+ */
+#define NSCD_CFG_GROUP_INFO_CACHE {12, 0x0fff}
+typedef struct nscd_cfg_cache {
+ nscd_cfg_group_info_t gi; /* config requirement */
+ nscd_bool_t enable; /* if false return NOSERVER */
+ nscd_bool_t per_user; /* if true per user access */
+ nscd_bool_t avoid_ns; /* if true avoid name service */
+ nscd_bool_t check_files; /* if true check file */
+ int check_interval; /* check interval */
+ int pos_ttl; /* time to live for +ve entries */
+ int neg_ttl; /* time to live for -ve entries */
+ int keephot; /* keep hot count */
+ int hint_size; /* size to return for a GETHINTS */
+ ulong_t maxentries; /* maximum entries allowed */
+ int suggestedsize; /* obsolete */
+ nscd_bool_t old_data_ok; /* obsolete */
+} nscd_cfg_cache_t;
+
+#define NSCD_CFG_CACHE_DEFAULTS \
+ { \
+ NSCD_CFG_GROUP_INFO_CACHE, \
+ nscd_true, nscd_false, nscd_false, nscd_true, \
+ _NSC_FILE_CHECK_TIME, 600, 10, 0, 1 << 11, 0, \
+ 0, nscd_false \
+ }
+
+/*
+ * cache backend stat group (per database)
+ */
+#define NSCD_CFG_STAT_GROUP_INFO_CACHE {9, 0x01ff}
+typedef struct nscd_cfg_stat_cache {
+ nscd_cfg_group_info_t gi; /* config requirement */
+ ulong_t pos_hits; /* hits on +ve entries */
+ ulong_t neg_hits; /* hits on -ve entries */
+ ulong_t pos_misses; /* misses on +ve entries */
+ ulong_t neg_misses; /* misses on -ve entries */
+ ulong_t entries; /* count of cache entries */
+ ulong_t drop_count; /* cache queries dropped */
+ ulong_t wait_count; /* cache queries queued */
+ ulong_t invalidate_count; /* count for cache invalidation */
+ double hitrate; /* computed from other fields */
+} nscd_cfg_stat_cache_t;
+
+typedef struct nsc_db {
+ /*
+ * Data
+ */
+ avl_tree_t tree;
+ nsc_entry_t **htable;
+ nsc_entry_t *qhead;
+ nsc_entry_t *qtail;
+ nsc_entry_t *reap_node;
+ int callnumber;
+ int dbop;
+ char *name;
+ mutex_t db_mutex;
+ int htsize;
+ enum hash_type {
+ nsc_ht_default = 0,
+ nsc_ht_prime = 1,
+ nsc_ht_power2 = 2
+ } hash_type;
+ enum db_type {
+ nsc_key_ces = 0,
+ nsc_key_cis = 1,
+ nsc_key_int = 2,
+ nsc_key_other = 3
+ } db_type;
+ /*
+ * Methods
+ */
+ uint_t (*gethash)(nss_XbyY_key_t *, int);
+ int (*compar)(const void *, const void *);
+ void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *);
+ /*
+ * Config
+ */
+ nscd_cfg_cache_t cfg;
+ time_t cfg_mtime;
+} nsc_db_t;
+
+
+typedef struct nsc_ctx {
+ char *dbname; /* cache name */
+ nscd_cfg_stat_cache_t stats; /* statistics */
+ nscd_cfg_cache_t cfg; /* configs */
+ time_t cfg_mtime; /* config last modified time */
+ rwlock_t cfg_rwlp; /* config rwlock */
+ mutex_t stats_mutex; /* stats mutex */
+ mutex_t file_mutex; /* file mutex */
+ time_t file_mtime; /* file last modified time */
+ time_t file_chktime; /* file last checked time */
+ off_t file_size; /* file size at last check */
+ ino_t file_ino; /* file inode at last check */
+ const char *file_name; /* filename for check_files */
+ int db_count; /* number of caches */
+ nsc_db_t *nsc_db[_NSC_MAX_DB]; /* caches */
+ waiter_t wait; /* lookup wait CV */
+ sema_t throttle_sema; /* throttle lookups */
+ sema_t revalidate_sema; /* revalidation threads */
+ nscd_bool_t revalidate_on; /* reval. thread started */
+ nscd_bool_t reaper_on; /* reaper thread started */
+} nsc_ctx_t;
+
+typedef struct nsc_lookup_args {
+ nsc_ctx_t *ctx;
+ nsc_db_t *nscdb;
+ void *buffer;
+ size_t bufsize;
+} nsc_lookup_args_t;
+
+#define CACHE_CTX_COUNT 20
+
+/* Context initialization */
+extern void passwd_init_ctx(nsc_ctx_t *);
+extern void group_init_ctx(nsc_ctx_t *);
+extern void host_init_ctx(nsc_ctx_t *);
+extern void ipnode_init_ctx(nsc_ctx_t *);
+extern void exec_init_ctx(nsc_ctx_t *);
+extern void prof_init_ctx(nsc_ctx_t *);
+extern void user_init_ctx(nsc_ctx_t *);
+extern void ether_init_ctx(nsc_ctx_t *);
+extern void rpc_init_ctx(nsc_ctx_t *);
+extern void proto_init_ctx(nsc_ctx_t *);
+extern void net_init_ctx(nsc_ctx_t *);
+extern void bootp_init_ctx(nsc_ctx_t *);
+extern void auuser_init_ctx(nsc_ctx_t *);
+extern void auth_init_ctx(nsc_ctx_t *);
+extern void serv_init_ctx(nsc_ctx_t *);
+extern void netmask_init_ctx(nsc_ctx_t *);
+extern void printer_init_ctx(nsc_ctx_t *);
+extern void project_init_ctx(nsc_ctx_t *);
+extern void tnrhtp_init_ctx(nsc_ctx_t *);
+extern void tnrhdb_init_ctx(nsc_ctx_t *);
+
+/* Functions used to throttle threads */
+extern int nscd_wait(waiter_t *, mutex_t *, uint8_t *);
+extern int nscd_signal(waiter_t *, uint8_t *);
+
+/* Cache creation and initialization */
+extern nscd_rc_t init_cache();
+extern nsc_db_t *make_cache(enum db_type, int, char *,
+ int (*compar) (const void *, const void *),
+ void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *),
+ uint_t (*gethash)(nss_XbyY_key_t *, int),
+ enum hash_type, int);
+
+/* Cache backend lookup */
+extern void nsc_lookup(nsc_lookup_args_t *, int);
+
+/* Cache backend info */
+extern void nsc_info(nsc_ctx_t *, char *, nscd_cfg_cache_t cfg[],
+ nscd_cfg_stat_cache_t stats[]);
+#ifdef NSCD_DEBUG
+extern int nsc_dump(char *, int);
+#endif /* NSCD_DEBUG */
+
+/* Cache invalidate */
+extern void nsc_invalidate(nsc_ctx_t *, char *, nsc_ctx_t **);
+
+/* Keep hot functions */
+extern nsc_keephot_t *maken(int);
+extern void *insertn(nsc_keephot_t *, uint_t, void *);
+
+/* hash related routines */
+extern uint_t cis_gethash(const char *, int);
+extern uint_t ces_gethash(const char *, int);
+extern uint_t db_gethash(const void *, int, int);
+
+extern void leave(int n);
+extern int get_cache_idx(char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_H */
diff --git a/usr/src/cmd/nscd/attrstr.c b/usr/src/cmd/nscd/getauth.c
index 1d4f162458..2a8ec60082 100644
--- a/usr/src/cmd/nscd/attrstr.c
+++ b/usr/src/cmd/nscd/getauth.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,22 +19,28 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <strings.h>
+/*
+ * Routines to handle getauth* calls in nscd
+ */
-int
-attr_strlen(char *s)
-{
- return (s ? strlen(s) : 0);
-}
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define NSC_NAME_AUTHATTR_BYNAME "getauthnam"
-char *
-attr_strcpy(char *dest, char *src)
-{
- return (strcpy(dest, src ? src : ""));
+void
+auth_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_AUTHATTR;
+ ctx->file_name = "/etc/security/auth_attr";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_AUTHATTR_BYNAME,
+ NSC_NAME_AUTHATTR_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
}
diff --git a/usr/src/cmd/nscd/getauuser.c b/usr/src/cmd/nscd/getauuser.c
new file mode 100644
index 0000000000..267bda6238
--- /dev/null
+++ b/usr/src/cmd/nscd/getauuser.c
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getauuser* calls in nscd
+ */
+
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define NSC_NAME_AUDITUSER_BYNAME "getauusernam"
+
+void
+auuser_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_AUDITUSER;
+ ctx->file_name = "/etc/security/audit_user";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_AUDITUSER_BYNAME,
+ NSC_NAME_AUDITUSER_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getbootp.c b/usr/src/cmd/nscd/getbootp.c
new file mode 100644
index 0000000000..6ee9b14273
--- /dev/null
+++ b/usr/src/cmd/nscd/getbootp.c
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle bootparams* calls in nscd
+ */
+
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define NSC_NAME_BOOTPARAMS_BYNAME "bootparams"
+
+void
+bootp_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_BOOTPARAMS;
+ ctx->file_name = "/etc/bootparams";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_cis,
+ NSS_DBOP_BOOTPARAMS_BYNAME,
+ NSC_NAME_BOOTPARAMS_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getether.c b/usr/src/cmd/nscd/getether.c
new file mode 100644
index 0000000000..ec5ff516c9
--- /dev/null
+++ b/usr/src/cmd/nscd/getether.c
@@ -0,0 +1,97 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle ether_*to* calls in nscd
+ */
+
+#include <stdlib.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <string.h>
+#include "cache.h"
+
+#define host_db ctx->nsc_db[0]
+#define addr_db ctx->nsc_db[1]
+
+#define NSC_NAME_ETHERS_HOSTTON "ether_hostton"
+#define NSC_NAME_ETHERS_NTOHOST "ether_ntohost"
+
+static void ether_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int ether_compar(const void *, const void *);
+static uint_t ether_gethash(nss_XbyY_key_t *, int);
+
+void
+ether_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_ETHERS;
+ ctx->file_name = "/etc/ethers";
+ ctx->db_count = 2;
+ host_db = make_cache(nsc_key_cis,
+ NSS_DBOP_ETHERS_HOSTTON,
+ NSC_NAME_ETHERS_HOSTTON,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+
+ addr_db = make_cache(nsc_key_other,
+ NSS_DBOP_ETHERS_NTOHOST,
+ NSC_NAME_ETHERS_NTOHOST,
+ ether_compar,
+ ether_getlogstr,
+ ether_gethash, nsc_ht_default, -1);
+}
+
+static int
+ether_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ if (ether_cmp(e1->key.ether, e2->key.ether) != 0) {
+ res = memcmp(e1->key.ether, e2->key.ether,
+ sizeof (struct ether_addr));
+ return (_NSC_INT_KEY_CMP(res, 0));
+ }
+ return (0);
+}
+
+static uint_t
+ether_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(key->ether, sizeof (struct ether_addr),
+ htsize));
+}
+
+static void
+ether_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ struct ether_addr *e;
+ e = (struct ether_addr *)argp->key.ether;
+ (void) snprintf(whoami, len, "%s [key=%x:%x:%x:%x:%x:%x]",
+ name,
+ e->ether_addr_octet[0], e->ether_addr_octet[1],
+ e->ether_addr_octet[2], e->ether_addr_octet[3],
+ e->ether_addr_octet[4], e->ether_addr_octet[5]);
+}
diff --git a/usr/src/cmd/nscd/getexec.c b/usr/src/cmd/nscd/getexec.c
index 8abb15723e..0de0cd44cb 100644
--- a/usr/src/cmd/nscd/getexec.c
+++ b/usr/src/cmd/nscd/getexec.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,504 +29,101 @@
* Routines to handle getexec* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
-#include <nss_dbdefs.h>
-
#include <exec_attr.h>
+#include "cache.h"
-#include <getxby_door.h>
-#include "server_door.h"
-#include "nscd.h"
-
-extern execstr_t *_getexecprof(char *, char *, char *, int, execstr_t *,
- char *, int, int *);
-
-static hash_t *nam_hash;
-static mutex_t db_lock = DEFAULTMUTEX;
-static waiter_t db_wait;
-
-static int getexec_namekeepalive(int keep, int interval);
-static int update_exec_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-static void getexec_invalidate_unlocked(void);
+static int execattr_compar(const void *, const void *);
+static uint_t execattr_gethash(nss_XbyY_key_t *, int);
+static void execattr_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+#define nam_db ctx->nsc_db[0]
+#define id_db ctx->nsc_db[1]
+#define nam_id_db ctx->nsc_db[2]
+#define NSC_NAME_EXECATTR_BYNAME "execattr_byname"
+#define NSC_NAME_EXECATTR_BYID "execattr_byid"
+#define NSC_NAME_EXECATTR_BYNAMEID "execattr_bynameid"
void
-getexec_init(void)
-{
- nam_hash = make_hash(current_admin.exec.nsc_suggestedsize);
+exec_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_EXECATTR;
+ ctx->file_name = "/etc/security/exec_attr";
+ ctx->db_count = 3;
+ nam_db = make_cache(nsc_key_other,
+ NSS_DBOP_EXECATTR_BYNAME,
+ NSC_NAME_EXECATTR_BYNAME,
+ execattr_compar,
+ execattr_getlogstr,
+ execattr_gethash, nsc_ht_default, -1);
+ id_db = make_cache(nsc_key_other,
+ NSS_DBOP_EXECATTR_BYID,
+ NSC_NAME_EXECATTR_BYID,
+ execattr_compar,
+ execattr_getlogstr,
+ execattr_gethash, nsc_ht_default, -1);
+ nam_id_db = make_cache(nsc_key_other,
+ NSS_DBOP_EXECATTR_BYNAMEID,
+ NSC_NAME_EXECATTR_BYNAMEID,
+ execattr_compar,
+ execattr_getlogstr,
+ execattr_gethash, nsc_ht_default, -1);
}
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_exec_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(gnam));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
-
-void
-getexec_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.exec.nsc_pos_ttl;
-
- if (slp < 60) {
- slp = 60;
- }
- if ((count = current_admin.exec.nsc_keephot) != 0) {
- interval = (slp / 2)/count;
- if (interval == 0) interval = 1;
- sleep(slp * 2 / 3);
- getexec_namekeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
+#define EXEC_STR_CMP(s1, s2) \
+ if ((a = s1) == NULL) \
+ a = z; \
+ if ((b = s2) == NULL) \
+ b = z; \
+ res = strcmp(a, b); \
+ if (res != 0) \
+ return (res > 0 ? 1 : -1);
static int
-getexec_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
+execattr_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1 = (nsc_entry_t *)n1;
+ nsc_entry_t *e2 = (nsc_entry_t *)n2;
+ _priv_execattr *ep1 = (_priv_execattr *)e1->key.attrp;
+ _priv_execattr *ep2 = (_priv_execattr *)e2->key.attrp;
+ int res;
+ const char *a, *b, *z = "";
- int i;
+ /* compare name */
+ EXEC_STR_CMP(ep1->name, ep2->name);
- if (!keep)
- return (0);
+ /* compare policy */
+ EXEC_STR_CMP(ep1->policy, ep2->policy);
- table = maken(keep);
- mutex_lock(&db_lock);
- operate_hash(nam_hash, do_findgnams, (char *)table);
- mutex_unlock(&db_lock);
+ /* compare type */
+ EXEC_STR_CMP(ep1->type, ep2->type);
- for (i = 1; i <= keep; i++) {
- char *tmp;
+ /* compare id */
+ EXEC_STR_CMP(ep1->id, ep2->id);
- u.ping.nsc_call.nsc_callnumber = GETEXECID;
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
- return (0);
+ /* compare search flag */
+ return (_NSC_INT_KEY_CMP(ep1->search_flag, ep2->search_flag));
}
-
-/*
- * This routine marks all entries as invalid
- *
- */
-
-void
-getexec_invalidate(void)
-{
- mutex_lock(&db_lock);
- getexec_invalidate_unlocked();
- mutex_unlock(&db_lock);
+static uint_t
+execattr_gethash(nss_XbyY_key_t *key, int htsize) {
+ _priv_execattr *ep = key->attrp;
+ char keys[1024];
+ int len;
+
+ len = snprintf(keys, sizeof (keys), "%s:%s:%s:%s:%d",
+ ep->name ? ep->name : "", ep->type ? ep->type : "",
+ ep->id ? ep->id : "", ep->policy ? ep->policy : "",
+ ep->search_flag);
+ return (db_gethash(keys, len, htsize));
}
static void
-getexec_invalidate_unlocked(void)
-{
- operate_hash_addr(nam_hash, do_invalidate, (char *)GETEXECID);
- current_admin.exec.nsc_invalidate_count++;
-}
-
-void
-getexec_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
- char *p_name;
- char *p_type;
- char *p_id;
- char *unique;
- char *lasts;
- char *sep = ":";
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.exec.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&db_lock);
-
- if (current_admin.exec.nsc_check_files) {
- struct stat buf;
-
- if (stat(EXECATTR_FILENAME, &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getexec_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getexec_lookup: looking for name %s\n",
- in->nsc_u.name);
- }
-
- for (;;) {
- if (attr_strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getexec_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("getexec_lookup: Name too long from pid "
- "%d uid %d\n", ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(nam_hash, in->nsc_u.name);
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused =
- sizeof (*out);
- current_admin.exec.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&db_wait, &db_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.exec.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- execstr_t *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.exec.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits =
- ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_exec_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1,
- in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update...
- * mark to prevent
- * pileups of threads if the name service is hanging....
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&db_lock);
-
- /*
- * Call non-caching version in libnsl.
- */
- unique = strdup(in->nsc_u.name);
- p_name = strtok_r(unique, sep, &lasts);
- p_type = strtok_r(NULL, sep, &lasts);
- p_id = strtok_r(NULL, sep, &lasts);
- p = _getexecprof(p_name,
- p_type,
- p_id,
- GET_ONE,
- &out->nsc_u.exec,
- out->nsc_u.buff + sizeof (execstr_t),
- bufferspace,
- &saved_errno);
-
- free(unique);
- mutex_lock(&db_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
-
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- logit("getexec_lookup: nscd COULDN'T FIND exec_attr name %s\n",
- in->nsc_u.name);
- }
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.exec.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &retb->nsc_data,
- retb->nsc_data.nsc_bufferbytesused);
- update_exec_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getexec_lookup: nscd FOUND exec_attr name %s\n",
- in->nsc_u.name);
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.exec.nsc_pos_cache_misses++;
- retb = fixbuffer(out, bufferspace);
- update_exec_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
- retb->nsc_hits++;
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.exec.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getexec_lookup: found name %s in cache\n",
- in->nsc_u.name);
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.exec.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getexec_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n", retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
- mutex_unlock(&db_lock);
-}
-
-/*ARGSUSED*/
-static int
-update_exec_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */
- free(*old);
- current_admin.exec.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&db_wait, (char **)old);
- }
-
- *old = new;
-
- if ((new != NULL) && (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.exec.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.exec.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.exec.nsc_neg_ttl;
- }
- }
- return (0);
-}
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_bucket_t *retb;
- nsc_return_t *out;
- char *dest;
- int offset;
- int strs;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = attr_strlen(in->nsc_u.exec.name) +
- attr_strlen(in->nsc_u.exec.policy) +
- attr_strlen(in->nsc_u.exec.type) +
- attr_strlen(in->nsc_u.exec.res1) +
- attr_strlen(in->nsc_u.exec.res2) +
- attr_strlen(in->nsc_u.exec.id) +
- attr_strlen(in->nsc_u.exec.attr) + EXECATTR_DB_NCOL;
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = strs + ((int)&out->nsc_u.exec - (int)out) +
- sizeof (execstr_t);
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (execstr_t);
- offset = (int)dest;
-
- attr_strcpy(dest, in->nsc_u.exec.name);
- strs = 1 + attr_strlen(in->nsc_u.exec.name);
- out->nsc_u.exec.name = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.policy);
- strs = 1 + attr_strlen(in->nsc_u.exec.policy);
- out->nsc_u.exec.policy = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.type);
- strs = 1 + attr_strlen(in->nsc_u.exec.type);
- out->nsc_u.exec.type = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.res1);
- strs = 1 + attr_strlen(in->nsc_u.exec.res1);
- out->nsc_u.exec.res1 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.res2);
- strs = 1 + attr_strlen(in->nsc_u.exec.res2);
- out->nsc_u.exec.res2 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.id);
- strs = 1 + attr_strlen(in->nsc_u.exec.id);
- out->nsc_u.exec.id = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.exec.attr);
- out->nsc_u.exec.attr = dest - offset;
-
- memcpy(in, out, out->nsc_bufferbytesused);
-
- return (retb);
-}
-
-void
-getexec_reaper(void)
-{
- nsc_reaper("getexec", nam_hash, &current_admin.exec, &db_lock);
+execattr_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ _priv_execattr *ep = argp->key.attrp;
+
+ (void) snprintf(whoami, len,
+ "%s [name=%s:type=%s:id=%s:policy=%s:flags=%d]",
+ name, check_null(ep->name), check_null(ep->type),
+ check_null(ep->id), check_null(ep->policy),
+ ep->search_flag);
}
diff --git a/usr/src/cmd/nscd/getgr.c b/usr/src/cmd/nscd/getgr.c
index 5bf10680b4..1fc9215248 100644
--- a/usr/src/cmd/nscd/getgr.c
+++ b/usr/src/cmd/nscd/getgr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,587 +29,51 @@
* Routines to handle getgr* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
+#include "cache.h"
-#include <getxby_door.h>
-#include "server_door.h"
-#include "nscd.h"
+#define nam_db ctx->nsc_db[0]
+#define gid_db ctx->nsc_db[1]
-static hash_t *uid_hash;
-static hash_t *nam_hash;
-static mutex_t group_lock = DEFAULTMUTEX;
-static waiter_t group_wait;
+#define NSC_NAME_GROUP_BYNAME "getgrnam"
+#define NSC_NAME_GROUP_BYGID "getgrgid"
-static void getgr_gidkeepalive(int keep, int interval);
-static void getgr_namekeepalive(int keep, int interval);
-static int update_gr_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findgids(nsc_bucket_t *ptr, int *table, int gid);
-static void do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-static void getgr_invalidate_unlocked(void);
-
-
-void
-getgr_init(void)
-{
- uid_hash = make_ihash(current_admin.group.nsc_suggestedsize);
- nam_hash = make_hash(current_admin.group.nsc_suggestedsize);
-
-}
-
-static void
-do_invalidate(nsc_bucket_t **ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_gr_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_findgids(nsc_bucket_t *ptr, int *table, int gid)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- insertn(table, ptr->nsc_hits, gid);
- }
-}
-
-static void
-do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(gnam));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
+static void grgid_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int grgid_compar(const void *, const void *);
+static uint_t grgid_gethash(nss_XbyY_key_t *, int);
void
-getgr_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.group.nsc_pos_ttl;
-
- if (slp < 60) {
- slp = 60;
- }
-
- if ((count = current_admin.group.nsc_keephot) != 0) {
- interval = (slp / 2)/count;
- if (interval == 0) interval = 1;
- sleep(slp * 2 / 3);
- getgr_gidkeepalive(count, interval);
- getgr_namekeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
-
-static void
-getgr_gidkeepalive(int keep, int interval)
-{
- int *table;
- nsc_data_t ping;
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&group_lock);
- operate_hash(uid_hash, do_findgids, (char *)table);
- mutex_unlock(&group_lock);
-
- for (i = 1; i <= keep; i++) {
- ping.nsc_call.nsc_callnumber = GETGRGID;
- if ((ping.nsc_call.nsc_u.gid = table[keep + 1 + i]) == -1)
- continue; /* unused slot in table */
- launch_update(&ping.nsc_call);
- sleep(interval);
- }
- free(table);
+group_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_GROUP;
+ ctx->file_name = "/etc/group";
+ ctx->db_count = 2;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_GROUP_BYNAME,
+ NSC_NAME_GROUP_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+ gid_db = make_cache(nsc_key_other,
+ NSS_DBOP_GROUP_BYGID,
+ NSC_NAME_GROUP_BYGID,
+ grgid_compar,
+ grgid_getlogstr,
+ grgid_gethash, nsc_ht_default, -1);
}
static void
-getgr_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&group_lock);
- operate_hash(nam_hash, do_findgnams, (char *)table);
- mutex_unlock(&group_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETGRNAM;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
-
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
-
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
-}
-
-
-/*
- * This routine marks all entries as invalid
- *
- */
-
-void
-getgr_invalidate(void)
-{
- mutex_lock(&group_lock);
- getgr_invalidate_unlocked();
- mutex_unlock(&group_lock);
-}
-
-static void
-getgr_invalidate_unlocked(void)
-{
- operate_hash_addr(nam_hash, do_invalidate, (char *)GETGRNAM);
- operate_hash_addr(uid_hash, do_invalidate, (char *)GETGRGID);
- current_admin.group.nsc_invalidate_count++;
-}
-
-void
-getgr_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.group.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&group_lock);
-
- if (current_admin.group.nsc_check_files) {
- struct stat buf;
-
- if (stat("/etc/group", &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getgr_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETGRGID) {
- logit("getgr_lookup: looking for gid %d\n",
- in->nsc_u.gid);
- } else {
- logit("getgr_lookup: looking for name %s\n",
- in->nsc_u.name);
- }
- }
-
- for (;;) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETGRGID) {
- bucket = get_hash(uid_hash, (char *)in->nsc_u.gid);
- } else {
- if (strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getgr_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("getgr_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(nam_hash, in->nsc_u.name);
- }
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /*
- * no threads available
- * cannot process now
- */
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.group.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&group_wait, &group_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.group.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- struct group *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.group.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits = ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_gr_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1,
- in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update...
- * mark to prevent pileups of threads if the name
- * service is hanging....
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&group_lock);
-
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETGRGID) {
- p = _uncached_getgrgid_r(in->nsc_u.gid, &out->nsc_u.grp,
- out->nsc_u.buff + sizeof (struct group),
- bufferspace);
- saved_errno = errno;
- } else {
- p = _uncached_getgrnam_r(in->nsc_u.name,
- &out->nsc_u.grp,
- out->nsc_u.buff + sizeof (struct group),
- bufferspace);
- saved_errno = errno;
- }
-
- mutex_lock(&group_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETGRGID) {
- logit("getgr_lookup: nscd COULDN'T FIND gid %d\n",
- in->nsc_u.gid);
- } else {
- logit("getgr_lookup: nscd COULDN'T FIND group name %s\n",
- in->nsc_u.name);
- }
- }
-
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.group.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &retb->nsc_data,
- retb->nsc_data.nsc_bufferbytesused);
- update_gr_bucket((nsc_bucket_t **)bucket,
- retb,
- in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETGRGID) {
- logit("getgr_lookup: nscd FOUND gid %d\n",
- in->nsc_u.gid);
- } else {
- logit("getgr_lookup: nscd FOUND group name %s\n",
- in->nsc_u.name);
- }
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.group.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
- update_gr_bucket((nsc_bucket_t **)bucket,
- retb,
- in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.group.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETGRGID) {
- logit("getgr_lookup: found gid %d in cache\n",
- in->nsc_u.gid);
- } else {
- logit("getgr_lookup: found name %s in cache\n",
- in->nsc_u.name);
- }
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.group.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETGRGID) {
- logit("getgr_lookup: %d marked as NOT FOUND in cache.\n",
- in->nsc_u.gid);
- } else {
- logit("getgr_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n", retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
-
- mutex_unlock(&group_lock);
+grgid_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%d]", name, argp->key.gid);
}
-/*ARGSUSED*/
static int
-update_gr_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */
- free(*old);
- current_admin.group.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&group_wait, (char **)old);
- }
+grgid_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
-
- *old = new;
-
- if ((new != NULL) && (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
-
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.group.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.group.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.group.nsc_neg_ttl;
- }
- }
- return (0);
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ return (_NSC_INT_KEY_CMP(e1->key.gid, e2->key.gid));
}
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- int group_members;
- int i;
- nsc_bucket_t *retb;
- nsc_return_t *out;
- char *dest;
- int offset;
- int strs;
- char **members;
- int pwlen;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = 0;
- strs += 1 + strlen(in->nsc_u.grp.gr_name);
- pwlen = strlen(in->nsc_u.grp.gr_passwd);
- if (pwlen < 4)
- pwlen = 4;
- strs += 1 + pwlen;
-
- group_members = 0;
- while (in->nsc_u.grp.gr_mem[group_members]) {
- strs += 1 + strlen(in->nsc_u.grp.gr_mem[group_members]);
- group_members++;
- }
-
- strs += (group_members+1) * sizeof (char *);
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = strs + ((int)&out->nsc_u.grp - (int)out) +
- sizeof (struct group);
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
-
- out->nsc_u.grp.gr_gid = in->nsc_u.grp.gr_gid;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (struct group);
- offset = (int)dest;
-
- members = (char **)dest;
- out->nsc_u.grp.gr_mem = (char **)(dest - offset);
- dest += (group_members+1) * sizeof (char *);
-
-
- strcpy(dest, in->nsc_u.grp.gr_name);
- strs = 1 + strlen(in->nsc_u.grp.gr_name);
- out->nsc_u.grp.gr_name = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.grp.gr_passwd);
- strs = 1 + pwlen;
- out->nsc_u.grp.gr_passwd = dest - offset;
- dest += strs;
-
- for (i = 0; i < group_members; i++) {
- members[i] = dest - offset;
- strcpy(dest, in->nsc_u.grp.gr_mem[i]);
- strs = 1 + strlen(in->nsc_u.grp.gr_mem[i]);
- dest += strs;
- }
- members[i] = NULL; /* null terminate list */
- memcpy(in, out, out->nsc_bufferbytesused);
-
- return (retb);
-}
-
-void
-getgr_uid_reaper()
-{
- nsc_reaper("gr_uid", uid_hash, &current_admin.group, &group_lock);
-}
-
-void
-getgr_nam_reaper()
-{
- nsc_reaper("gr_nam", nam_hash, &current_admin.group, &group_lock);
+static uint_t
+grgid_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (key->gid % htsize);
}
diff --git a/usr/src/cmd/nscd/gethost.c b/usr/src/cmd/nscd/gethost.c
index c38b7f0b2b..b0cee1ad7e 100644
--- a/usr/src/cmd/nscd/gethost.c
+++ b/usr/src/cmd/nscd/gethost.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,654 +29,73 @@
* Routines to handle gethost* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
+#include <stdlib.h>
#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
-
-#include "getxby_door.h"
-#include "server_door.h"
-#include "nscd.h"
-
-static hash_t *addr_hash;
-static hash_t *hnam_hash;
-static mutex_t host_lock = DEFAULTMUTEX;
-static waiter_t host_wait;
-
-static void gethost_addrkeepalive(int keep, int interval);
-static void gethost_invalidate_unlocked(void);
-static void gethost_namekeepalive(int keep, int interval);
-static int addr_to_int(char *addr);
-static int int_to_addr(int h);
-static void update_host_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findhaddrs(nsc_bucket_t *ptr, int *table, int intaddr);
-static void do_findhnams(nsc_bucket_t *ptr, int *table, char *name);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-
-static int
-addr_to_int(char *addr)
-{
- union {
- char data[4];
- int hashval;
- } u;
-
-/*
- * following code is byte order dependant, but since all we use this for
- * is hashing this works out just fine.
- */
- u.data[0] = *addr++;
- u.data[1] = *addr++;
- u.data[2] = *addr++;
- u.data[3] = *addr++;
-
- return (u.hashval);
-}
-
-static int
-int_to_addr(int h)
-{
- union {
- char data[4];
- int hashval;
- } u;
-
-/*
- * following code is byte order dependant, but since all we use this for
- * is hashing this works out just fine.
- */
- u.hashval = h;
- return (* ((int *)u.data));
-}
-
-void
-gethost_init(void)
-{
- addr_hash = make_ihash(current_admin.host.nsc_suggestedsize);
- hnam_hash = make_hash(current_admin.host.nsc_suggestedsize);
-}
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "cache.h"
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_host_bucket(ptr, NULL, callnumber);
- }
-}
+#define hnam_db ctx->nsc_db[0]
+#define addr_db ctx->nsc_db[1]
-static void
-do_findhnams(nsc_bucket_t *ptr, int *table, char *name)
-{
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
+#define NSC_NAME_HOSTS_BYNAME "gethostbyname"
+#define NSC_NAME_HOSTS_BYADDR "gethostbyaddr"
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(name));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
-
-static void
-do_findhaddrs(nsc_bucket_t *ptr, int *table, int intaddr)
-{
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- insertn(table, ptr->nsc_hits, int_to_addr(intaddr));
- }
-}
+static int hostaddr_compar(const void *, const void *);
+static uint_t hostaddr_gethash(nss_XbyY_key_t *, int);
+static void hostaddr_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
void
-gethost_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.host.nsc_pos_ttl;
-
- if (slp < 60)
- slp = 60;
- count = current_admin.host.nsc_keephot;
- if (count != 0) {
- interval = (slp/2)/count;
- if (interval == 0) interval = 1;
- sleep(slp*2/3);
- gethost_namekeepalive(count, interval);
- gethost_addrkeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
-
-static void
-gethost_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&host_lock);
- operate_hash(hnam_hash, do_findhnams, (char *)table);
- mutex_unlock(&host_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETHOSTBYNAME;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
- if (current_admin.debug_level >= DBG_ALL)
- logit("keepalive: reviving host %s\n", tmp);
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
-
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
-}
-
-static void
-gethost_addrkeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + 80];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&host_lock);
- operate_hash(addr_hash, do_findhaddrs, (char *)table);
- mutex_unlock(&host_lock);
-
- for (i = 1; i <= keep; i++) {
- int tmp;
- u.ping.nsc_call.nsc_callnumber = GETHOSTBYADDR;
-
- if ((tmp = table[keep + 1 + i]) == -1)
- continue; /* unused slot in table */
- u.ping.nsc_call.nsc_u.addr.a_type = AF_INET;
- u.ping.nsc_call.nsc_u.addr.a_length = sizeof (int);
- memcpy(u.ping.nsc_call.nsc_u.addr.a_data, &tmp, sizeof (int));
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- free(table);
-}
-
-/*
- * This routine marks all entries as invalid
- *
- */
-void
-gethost_invalidate(void)
-{
- mutex_lock(&host_lock);
- gethost_invalidate_unlocked();
- mutex_unlock(&host_lock);
-}
-
-static void
-gethost_invalidate_unlocked(void)
-{
- operate_hash_addr(hnam_hash, do_invalidate, (char *)GETHOSTBYNAME);
- operate_hash_addr(addr_hash, do_invalidate, (char *)GETHOSTBYADDR);
- current_admin.host.nsc_invalidate_count++;
-}
-
-void
-gethost_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.host.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&host_lock);
-
- if (current_admin.host.nsc_check_files) {
- struct stat buf;
+host_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_HOSTS;
+ ctx->db_count = 2;
+ ctx->file_name = "/etc/inet/hosts";
- if (stat("/etc/hosts", &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- gethost_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
-
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETHOSTBYADDR) {
- logit("gethost_lookup: looking for address %s\n",
- inet_ntoa(*((struct in_addr *)in->nsc_u.addr.a_data)));
- } else {
- logit("gethost_lookup: looking for hostname %s\n",
- in->nsc_u.name);
- }
- }
-
- for (;;) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETHOSTBYADDR) {
- bucket = get_hash(addr_hash,
- (char *)addr_to_int(in->nsc_u.addr.a_data));
- } else { /* bounce excessively long requests */
- if (strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("gethost_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("gethost_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(hnam_hash, in->nsc_u.name);
- }
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.host.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&host_wait, &host_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.host.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- struct hostent *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.host.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits = ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent or out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_host_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1,
- in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update... mark
- * to prevent pileups of threads if the name service
- * is hanging....
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&host_lock);
-
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETHOSTBYADDR) {
- p = _uncached_gethostbyaddr_r(in->nsc_u.addr.a_data,
- in->nsc_u.addr.a_length,
- in->nsc_u.addr.a_type,
- &out->nsc_u.hst,
- out->nsc_u.buff+sizeof (struct hostent),
- bufferspace,
- &saved_errno);
- } else {
- p = _uncached_gethostbyname_r(in->nsc_u.name,
- &out->nsc_u.hst,
- out->nsc_u.buff+sizeof (struct hostent),
- bufferspace,
- &saved_errno);
- }
-
- mutex_lock(&host_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETHOSTBYADDR) {
- logit("gethost_lookup: nscd COULDN'T FIND address %s\n",
- inet_ntoa(*((struct in_addr *)in->nsc_u.addr.a_data)));
- } else {
- logit("gethost_lookup: nscd COULDN'T FIND host name %s\n",
- in->nsc_u.name);
- }
- }
+ hnam_db = make_cache(nsc_key_cis,
+ NSS_DBOP_HOSTS_BYNAME,
+ NSC_NAME_HOSTS_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.host.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
- update_host_bucket((nsc_bucket_t **)bucket, retb,
- in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETHOSTBYADDR) {
- logit("gethost_lookup: nscd FOUND addr %s\n",
- inet_ntoa(*((struct in_addr *)in->nsc_u.addr.a_data)));
- } else {
- logit("gethost_lookup: nscd FOUND host name %s\n",
- in->nsc_u.name);
- }
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.host.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
-
- update_host_bucket((nsc_bucket_t **)bucket, retb,
- in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.host.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETHOSTBYADDR) {
- logit("gethost_lookup: found address %s in cache\n",
- inet_ntoa(*((struct in_addr *)in->nsc_u.addr.a_data)));
- } else {
- logit("gethost_lookup: found host name %s in cache\n",
- in->nsc_u.name);
- }
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.host.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETHOSTBYADDR) {
- logit("gethost_lookup: %s marked as NOT FOUND in cache.\n",
- inet_ntoa(*((struct in_addr *)in->nsc_u.addr.a_data)));
- } else {
- logit("gethost_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n", retb->nsc_timestamp);
- /* cleared by deletion of old data */
- retb->nsc_status |= ST_UPDATE_PENDING;
- launch_update(in);
- }
- }
-
-getout:
-
- mutex_unlock(&host_lock);
+ addr_db = make_cache(nsc_key_other,
+ NSS_DBOP_HOSTS_BYADDR,
+ NSC_NAME_HOSTS_BYADDR,
+ hostaddr_compar,
+ hostaddr_getlogstr,
+ hostaddr_gethash, nsc_ht_default, -1);
}
-/*ARGSUSED*/
static void
-update_host_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) {
- /* old data exists */
- free(*old);
- current_admin.host.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
+hostaddr_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ char addr[INET6_ADDRSTRLEN];
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&host_wait, (char **)old);
- }
-
-
-
- *old = new;
-
- if ((new != NULL) &&
- (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
-
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.host.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.host.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.host.nsc_neg_ttl;
- }
+ if (inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr, addr,
+ sizeof (addr)) == NULL) {
+ (void) snprintf(whoami, len, "%s", name);
+ } else {
+ (void) snprintf(whoami, len, "%s [key=%s, addrtype=%d]",
+ name, addr, argp->key.hostaddr.type);
}
}
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_return_t *out;
- nsc_bucket_t *retb;
- char *dest;
- char **aliaseslist;
- char **addrlist;
- int offset;
- int strs;
- int i;
- int numaliases;
- int numaddrs;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = 1 + strlen(in->nsc_u.hst.h_name);
- for (numaliases = 0; in->nsc_u.hst.h_aliases[numaliases]; numaliases++)
- strs += 1 + strlen(in->nsc_u.hst.h_aliases[numaliases]);
- strs += sizeof (char *) * (numaliases+1);
- for (numaddrs = 0; in->nsc_u.hst.h_addr_list[numaddrs]; numaddrs++)
- strs += in->nsc_u.hst.h_length;
- strs += sizeof (char *) * (numaddrs+1+3);
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = sizeof (*in) + strs;
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (struct hostent);
-
- offset = (int)dest;
-
- /*
- * allocat the h_aliases list and the h_addr_list first to align 'em.
- */
- aliaseslist = (char **)dest;
-
- dest += sizeof (char *) * (numaliases+1);
-
- addrlist = (char **)dest;
-
- dest += sizeof (char *) * (numaddrs+1);
-
- strcpy(dest, in->nsc_u.hst.h_name);
- strs = 1 + strlen(in->nsc_u.hst.h_name);
- out->nsc_u.hst.h_name = dest - offset;
- dest += strs;
-
-
- /*
- * fill out the h_aliases list
- */
- for (i = 0; i < numaliases; i++) {
- strcpy(dest, in->nsc_u.hst.h_aliases[i]);
- strs = 1 + strlen(in->nsc_u.hst.h_aliases[i]);
- aliaseslist[i] = dest - offset;
- dest += strs;
- }
- aliaseslist[i] = 0; /* null term ptr chain */
-
- out->nsc_u.hst.h_aliases = (char **)((int)aliaseslist-offset);
-
- /*
- * fill out the h_addr list
- */
-
- dest = (char *)(((int)dest + 3) & ~3);
-
- for (i = 0; i < numaddrs; i++) {
- memcpy(dest, in->nsc_u.hst.h_addr_list[i],
- in->nsc_u.hst.h_length);
- strs = in->nsc_u.hst.h_length;
- addrlist[i] = dest - offset;
- dest += strs;
- dest = (char *)(((int)dest + 3) & ~3);
- }
-
- addrlist[i] = 0; /* null term ptr chain */
-
- out->nsc_u.hst.h_addr_list = (char **)((int)addrlist-offset);
-
- out->nsc_u.hst.h_length = in->nsc_u.hst.h_length;
- out->nsc_u.hst.h_addrtype = in->nsc_u.hst.h_addrtype;
-
- memcpy(in, &(retb->nsc_data), retb->nsc_data.nsc_bufferbytesused);
-
- return (retb);
-
-}
-
-void
-gethost_nam_reaper()
-{
- nsc_reaper("gethost_nam", hnam_hash, &current_admin.host, &host_lock);
-}
-
-void
-gethost_addr_reaper()
-{
- nsc_reaper("gethost_addr", addr_hash, &current_admin.host, &host_lock);
+static int
+hostaddr_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ l1 = e1->key.hostaddr.len;
+ l2 = e2->key.hostaddr.len;
+ res = memcmp(e1->key.hostaddr.addr, e2->key.hostaddr.addr,
+ (l2 > l1)?l1:l2);
+ return ((res) ? _NSC_INT_KEY_CMP(res, 0) : _NSC_INT_KEY_CMP(l1, l2));
+}
+
+static uint_t
+hostaddr_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(key->hostaddr.addr,
+ key->hostaddr.len, htsize));
}
diff --git a/usr/src/cmd/nscd/getnet.c b/usr/src/cmd/nscd/getnet.c
new file mode 100644
index 0000000000..468e8ffa68
--- /dev/null
+++ b/usr/src/cmd/nscd/getnet.c
@@ -0,0 +1,120 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getnet* calls in nscd
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define addr_db ctx->nsc_db[1]
+
+#define NSC_NAME_NETWORKS_BYNAME "getnetbyname"
+#define NSC_NAME_NETWORKS_BYADDR "getnetbyaddr"
+
+static int netaddr_compar(const void *, const void *);
+static uint_t netaddr_gethash(nss_XbyY_key_t *, int);
+static void netaddr_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+
+void
+net_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_NETWORKS;
+ ctx->db_count = 2;
+ ctx->file_name = "/etc/inet/networks";
+
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_NETWORKS_BYNAME,
+ NSC_NAME_NETWORKS_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+
+ addr_db = make_cache(nsc_key_other,
+ NSS_DBOP_NETWORKS_BYADDR,
+ NSC_NAME_NETWORKS_BYADDR,
+ netaddr_compar,
+ netaddr_getlogstr,
+ netaddr_gethash, nsc_ht_default, -1);
+}
+
+static void
+netaddr_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ if (argp->key.netaddr.type == AF_INET) {
+ uint32_t net;
+ uchar_t *up;
+
+ net = htonl(argp->key.netaddr.net);
+ up = (uchar_t *)&net;
+
+ if (up[0])
+ (void) snprintf(whoami, len, "%s [key=%d.%d.%d.%d]",
+ name,
+ up[0], up[1], up[2], up[3]);
+ else if (up[1])
+ (void) snprintf(whoami, len, "%s [key=%d.%d.%d]",
+ name,
+ up[1], up[2], up[3]);
+ else if (up[2])
+ (void) snprintf(whoami, len, "%s [key=%d.%d]",
+ name,
+ up[2], up[3]);
+ else
+ (void) snprintf(whoami, len, "%s [key=%d]",
+ name,
+ up[3]);
+ } else {
+ (void) snprintf(whoami, len, "%s [key=%d, %d]",
+ name,
+ argp->key.netaddr.net, argp->key.netaddr.type);
+ }
+}
+
+static int
+netaddr_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+
+ if (e1->key.netaddr.type > e2->key.netaddr.type)
+ return (1);
+ else if (e1->key.netaddr.type < e2->key.netaddr.type)
+ return (-1);
+
+ return (_NSC_INT_KEY_CMP(e1->key.netaddr.net, e2->key.netaddr.net));
+}
+
+static uint_t
+netaddr_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(&key->netaddr.net,
+ sizeof (key->netaddr.net), htsize));
+}
diff --git a/usr/src/cmd/nscd/getnetmasks.c b/usr/src/cmd/nscd/getnetmasks.c
new file mode 100644
index 0000000000..81b709e104
--- /dev/null
+++ b/usr/src/cmd/nscd/getnetmasks.c
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getnetmask* calls in nscd
+ */
+
+#include "cache.h"
+
+#define key_db ctx->nsc_db[0]
+
+#define NSC_NAME_NETMASKS_BYNET "getnetmaskbykey"
+
+void
+netmask_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_NETMASKS;
+ ctx->db_count = 1;
+ ctx->file_name = "/etc/inet/netmasks";
+
+ key_db = make_cache(nsc_key_ces,
+ NSS_DBOP_NETMASKS_BYNET,
+ NSC_NAME_NETMASKS_BYNET,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getnode.c b/usr/src/cmd/nscd/getnode.c
index a744841197..fdf255672d 100644
--- a/usr/src/cmd/nscd/getnode.c
+++ b/usr/src/cmd/nscd/getnode.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,772 +31,120 @@
* related to them in the nscd will remain as getnode*.
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include <strings.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <inet/ip6.h>
+#include "cache.h"
-#include "getxby_door.h"
-#include "server_door.h"
-#include "nscd.h"
+static int ipaddr_compar(const void *, const void *);
+static uint_t ipaddr_gethash(nss_XbyY_key_t *, int);
+static void ipaddr_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
-static hash_t *addr_hash; /* node address hash */
-static hash_t *nnam_hash; /* node name hash */
-static mutex_t node_lock = DEFAULTMUTEX;
-static waiter_t node_wait;
+static int ipname_compar(const void *, const void *);
+static uint_t ipname_gethash(nss_XbyY_key_t *, int);
+static void ipname_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
-static void getnode_addrkeepalive(int keep, int interval);
-static void getnode_invalidate_unlocked(void);
-static void getnode_namekeepalive(int keep, int interval);
-static void update_node_bucket(nsc_bucket_t ** old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findnaddrs(nsc_bucket_t *ptr, int *table, char *addr);
-static void do_findnnams(nsc_bucket_t *ptr, int *table, char *name);
-static void do_invalidate(nsc_bucket_t ** ptr, int callnumber);
+#define nnam_db ctx->nsc_db[0]
+#define addr_db ctx->nsc_db[1]
-/*
- * Create a combined key
- * combined key =
- * name + ":" + af_family(in %d format) + ":" + flags(in %d format)
- * name = foo, af_family = 26, flags = 3, addrconfig = 1
- * key = "foo:26:3"
- * The string is allocated and caller has to free it.
- *
- * Insert ":" in between to ensure the uniqueness of the key.
- *
- * af_family: [2 | 26] ([AF_INET | AF_INET6])
- * flags: 0 - strict
- * 1 - AI_V4MAPPED
- * 3 - (AI_V4MAPPED | AI_ALL)
- * 4 - AI_ADDRCONFIG
- * 5 - AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG)
- * 7 - (AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG)
- */
-static char *
-get_ipnode_combined_key(nsc_call_t *in) {
- int len;
- char *key;
- char af_str[8]; /* in %d format */
- char flags_str[8]; /* in %d format */
-
- snprintf(af_str, 8, "%d", in->nsc_u.ipnode.af_family);
- snprintf(flags_str, 8, "%d", in->nsc_u.ipnode.flags);
- /* name + ":" + af_str + ":" + flags_str + 1 */
- len = strlen(in->nsc_u.ipnode.name) + strlen(af_str) +
- strlen(flags_str) + 3;
-
- if ((key = (char *)malloc(len)) == NULL)
- return (NULL);
-
- snprintf(key, len, "%s:%s:%s", in->nsc_u.ipnode.name, af_str,
- flags_str);
- return (key);
-}
-/*
- * Parse key and copy the values to out
- */
-static void
-copy_ipnode_combined_key(char *key, nsc_call_t *out) {
- char *token, *lasts;
-
- if ((token = strtok_r(key, ":", &lasts)) != NULL) {
- /* copy name */
- (void) strncpy(out->nsc_u.ipnode.name, token,
- NSCDMAXNAMELEN);
- if ((token = strtok_r(NULL, ":", &lasts)) != NULL) {
- /* Copy af_family */
- out->nsc_u.ipnode.af_family = atoi(token);
-
- if ((token = strtok_r(NULL, ":", &lasts)) != NULL) {
- /* Copy flags */
- out->nsc_u.ipnode.flags = atoi(token);
- }
- }
- }
-}
-
-static void
-safe_inet_ntop(int af, const void *addr, char *cp, size_t size)
-{
- if (inet_ntop(af, addr, cp, size) != cp) {
- /*
- * Called only for logging purposes...
- * this should never happen in the nscd... but
- * just in case we'll make sure we have a
- * plausible error message.
- */
- (void) snprintf(cp, size, "<inet_ntop returned %s>",
- strerror(errno));
- }
-}
-
-void
-getnode_init(void)
-{
- addr_hash = make_hash(current_admin.node.nsc_suggestedsize);
- nnam_hash = make_hash(current_admin.node.nsc_suggestedsize);
-}
-
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_node_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_findnnams(nsc_bucket_t *ptr, int *table, char *name)
-{
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(name));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
-
-static void
-do_findnaddrs(nsc_bucket_t *ptr, int *table, char *addr)
-{
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
-
- /* leave pending calls alone */
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(addr));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
+#define NSC_NAME_IPNODES_BYNAME "getipnodebyname"
+#define NSC_NAME_IPNODES_BYADDR "getipnodebyaddr"
void
-getnode_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.node.nsc_pos_ttl;
-
- if (slp < 60)
- slp = 60;
-
- if ((count = current_admin.node.nsc_keephot) != 0) {
- interval = (slp/2)/count;
- if (interval == 0) interval = 1;
- (void) sleep(slp*2/3);
- getnode_namekeepalive(count, interval);
- getnode_addrkeepalive(count, interval);
- } else {
- (void) sleep(slp);
- }
- }
-}
-
-static void
-getnode_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- (void) mutex_lock(&node_lock);
- operate_hash(nnam_hash, do_findnnams, (char *)table);
- (void) mutex_unlock(&node_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETIPNODEBYNAME;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
- if (current_admin.debug_level >= DBG_ALL)
- logit("keepalive: reviving node %s\n", tmp);
- copy_ipnode_combined_key(tmp, &u.ping.nsc_call);
-
- launch_update(&u.ping.nsc_call);
- (void) sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
+ipnode_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_IPNODES;
+ ctx->file_name = "/etc/inet/ipnodes";
+ ctx->db_count = 2;
+ nnam_db = make_cache(nsc_key_other,
+ NSS_DBOP_IPNODES_BYNAME,
+ NSC_NAME_IPNODES_BYNAME,
+ ipname_compar,
+ ipname_getlogstr,
+ ipname_gethash, nsc_ht_default, -1);
+
+ addr_db = make_cache(nsc_key_other,
+ NSS_DBOP_IPNODES_BYADDR,
+ NSC_NAME_IPNODES_BYADDR,
+ ipaddr_compar,
+ ipaddr_getlogstr,
+ ipaddr_gethash, nsc_ht_default, -1);
+}
+
+static int
+ipaddr_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+
+ if (e1->key.hostaddr.type > e2->key.hostaddr.type)
+ return (1);
+ else if (e1->key.hostaddr.type < e2->key.hostaddr.type)
+ return (-1);
+
+ l1 = e1->key.hostaddr.len;
+ l2 = e2->key.hostaddr.len;
+ res = memcmp(e1->key.hostaddr.addr, e2->key.hostaddr.addr,
+ (l2 > l1)?l1:l2);
+ return ((res) ? _NSC_INT_KEY_CMP(res, 0) : _NSC_INT_KEY_CMP(l1, l2));
+}
+
+static uint_t
+ipaddr_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(key->hostaddr.addr,
+ key->hostaddr.len, htsize));
}
static void
-getnode_addrkeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + 80];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- (void) mutex_lock(&node_lock);
- operate_hash(addr_hash, do_findnaddrs, (char *)table);
- (void) mutex_unlock(&node_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- char addr[IPV6_ADDR_LEN];
-
- u.ping.nsc_call.nsc_callnumber = GETIPNODEBYADDR;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* enused slot in table */
- u.ping.nsc_call.nsc_u.addr.a_type = AF_INET6;
- u.ping.nsc_call.nsc_u.addr.a_length = IPV6_ADDR_LEN;
- if (inet_pton(AF_INET6, (const char *) tmp, (void *) addr) !=
- 1)
- continue; /* illegal address - skip it */
- else {
- (void) memcpy(u.ping.nsc_call.nsc_u.addr.a_data,
- addr, IPV6_ADDR_LEN);
- if (current_admin.debug_level >= DBG_ALL)
- logit("keepalive: reviving address %s\n", tmp);
- launch_update(&u.ping.nsc_call);
- }
- (void) sleep(interval);
- }
+ipaddr_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ char addr[INET6_ADDRSTRLEN];
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
+ if (inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr, addr,
+ sizeof (addr)) == NULL) {
+ (void) snprintf(whoami, len, "%s", name);
+ } else {
+ (void) snprintf(whoami, len, "%s [key=%s addrtype=%d]",
+ name,
+ addr, argp->key.hostaddr.type);
}
-
- free(table);
}
-/*
- * This routine marks all entries as invalid
- *
- */
-
-void
-getnode_invalidate(void)
-{
- (void) mutex_lock(&node_lock);
- getnode_invalidate_unlocked();
- (void) mutex_unlock(&node_lock);
-}
+static int
+ipname_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
-static void
-getnode_invalidate_unlocked(void)
-{
- operate_hash_addr(nnam_hash, do_invalidate, (char *)GETIPNODEBYNAME);
- operate_hash_addr(addr_hash, do_invalidate, (char *)GETIPNODEBYADDR);
- current_admin.node.nsc_invalidate_count++;
-}
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
-/*
- * Mark only the ipnodebyname cache entries as invalid
- */
+ if (e1->key.ipnode.af_family > e2->key.ipnode.af_family)
+ return (1);
+ else if (e1->key.ipnode.af_family < e2->key.ipnode.af_family)
+ return (-1);
-void
-getnode_name_invalidate(void)
-{
- (void) mutex_lock(&node_lock);
- operate_hash_addr(nnam_hash, do_invalidate, (char *)GETIPNODEBYNAME);
- current_admin.node.nsc_invalidate_count++;
- (void) mutex_unlock(&node_lock);
+ l1 = strlen(e1->key.ipnode.name);
+ l2 = strlen(e2->key.ipnode.name);
+ res = strncasecmp(e1->key.ipnode.name, e2->key.ipnode.name,
+ (l1 > l2)?l1:l2);
+ return (_NSC_INT_KEY_CMP(res, 0));
}
-void
-getnode_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket, *key;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.node.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- (void) mutex_lock(&node_lock);
-
- if (current_admin.node.nsc_check_files) {
- struct stat buf;
-
- if (stat("/etc/inet/ipnodes", &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getnode_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
-
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- safe_inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data, addr,
- sizeof (addr));
- logit("getnode_lookup: looking for address %s\n", addr);
- } else {
- logit("getnode_lookup: looking for nodename %s:%d:%d\n",
- in->nsc_u.ipnode.name,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags);
- }
- }
-
- for (;;) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- if (inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data,
- addr, sizeof (addr)) == NULL) {
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(addr_hash, addr);
- } else { /* bounce excessively long requests */
- if (strlen(in->nsc_u.ipnode.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getnode_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("getnode_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- if ((key = get_ipnode_combined_key(in)) == NULL) {
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
-
- bucket = get_hash(nnam_hash, key);
- free(key);
- }
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.node.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&node_wait, &node_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.node.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- struct hostent *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (* out);
- current_admin.node.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits = ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent or out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_node_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1,
- in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update... mark to
- * prevent pileups of threads if the name service is hanging...
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- (void) mutex_unlock(&node_lock);
-
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETIPNODEBYADDR) {
- p = _uncached_getipnodebyaddr(in->nsc_u.addr.a_data,
- in->nsc_u.addr.a_length,
- in->nsc_u.addr.a_type,
- &out->nsc_u.hst,
- out->nsc_u.buff+sizeof (struct hostent),
- bufferspace,
- &saved_errno);
- } else {
- p = _uncached_getipnodebyname(in->nsc_u.ipnode.name,
- &out->nsc_u.hst,
- out->nsc_u.buff+sizeof (struct hostent),
- bufferspace,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags,
- &saved_errno);
- }
-
- (void) mutex_lock(&node_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- safe_inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data,
- addr, sizeof (addr));
- logit("getnode_lookup: nscd COULDN'T "\
- "FIND address %s\n", addr);
- } else {
- logit("getnode_lookup: nscd COULDN'T "\
- "FIND node name %s:%d:%d\n",
- in->nsc_u.ipnode.name,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags);
- }
- }
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.node.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_errno = saved_errno;
- (void) memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
- update_node_bucket((nsc_bucket_t **)bucket, retb,
- in->nsc_callnumber);
- goto getout;
- }
-
- else {
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- safe_inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data,
- addr, sizeof (addr));
- logit("getnode_lookup: nscd FOUND "\
- "addr %s\n", addr);
- } else {
- logit("getnode_lookup: nscd FOUND "\
- "node name %s:%d:%d\n",
- in->nsc_u.ipnode.name,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags);
- }
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.node.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
-
- update_node_bucket((nsc_bucket_t **)bucket, retb,
- in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- (void) memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.node.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- safe_inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data,
- addr, sizeof (addr));
- logit("getnode_lookup: found address "\
- "%s in cache\n", addr);
- } else {
- logit("getnode_lookup: found node "\
- "name %s:%d:%d in cache\n",
- in->nsc_u.ipnode.name,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags);
- }
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.node.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETIPNODEBYADDR) {
- char addr[INET6_ADDRSTRLEN];
- safe_inet_ntop(AF_INET6,
- (const void *)in->nsc_u.addr.a_data,
- addr, sizeof (addr));
- logit("getnode_lookup: %s marked as "\
- "NOT FOUND in cache.\n", addr);
- } else {
- logit("getnode_lookup: %s:%d:%d marked"\
- " as NOT FOUND in cache.\n",
- in->nsc_u.ipnode.name,
- in->nsc_u.ipnode.af_family,
- in->nsc_u.ipnode.flags);
- }
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n",
- retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
-
- (void) mutex_unlock(&node_lock);
+static uint_t
+ipname_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (cis_gethash(key->ipnode.name, htsize));
}
-
-/*ARGSUSED*/
static void
-update_node_bucket(nsc_bucket_t ** old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */
- free(*old);
- current_admin.node.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&node_wait, (char **)old);
- }
-
- *old = new;
-
- if ((new != NULL) &&
- (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
-
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.node.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.node.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.node.nsc_neg_ttl;
- }
- }
-}
-
-/* Allocate a bucket to fit the data(nsc_return_t *in size) */
-/* copy the data into the bucket and return the bucket */
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_return_t *out;
- nsc_bucket_t *retb;
- char *dest;
- char ** aliaseslist;
- char ** addrlist;
- int offset;
- int strs;
- int i;
- int numaliases;
- int numaddrs;
-
- /* find out the size of the data block we're going to need */
-
- strs = 1 + strlen(in->nsc_u.hst.h_name);
- for (numaliases = 0; in->nsc_u.hst.h_aliases[numaliases]; numaliases++)
- strs += 1 + strlen(in->nsc_u.hst.h_aliases[numaliases]);
- strs += sizeof (char *) * (numaliases+1);
- for (numaddrs = 0; in->nsc_u.hst.h_addr_list[numaddrs]; numaddrs++)
- strs += in->nsc_u.hst.h_length;
- strs += sizeof (char *) * (numaddrs+1+3);
-
- /* allocate it and copy it in code doesn't assume packing */
- /* order in original buffer */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = sizeof (*in) + strs;
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (struct hostent);
- offset = (int)dest;
-
- /* allocat the h_aliases list and the h_addr_list first to align 'em. */
- aliaseslist = (char **)dest;
-
- dest += sizeof (char *) * (numaliases+1);
-
- addrlist = (char **)dest;
-
- dest += sizeof (char *) * (numaddrs+1);
-
- (void) strcpy(dest, in->nsc_u.hst.h_name);
- strs = 1 + strlen(in->nsc_u.hst.h_name);
- out->nsc_u.hst.h_name = dest - offset;
- dest += strs;
-
-
- /* fill out the h_aliases list */
-
- for (i = 0; i < numaliases; i++) {
- (void) strcpy(dest, in->nsc_u.hst.h_aliases[i]);
- strs = 1 + strlen(in->nsc_u.hst.h_aliases[i]);
- aliaseslist[i] = dest - offset;
- dest += strs;
- }
- aliaseslist[i] = 0; /* null term ptr chain */
-
- out->nsc_u.hst.h_aliases = (char **)((int)aliaseslist-offset);
-
- /* fill out the h_addr list */
-
- dest = (char *)(((int)dest + 3) & ~3);
-
- for (i = 0; i < numaddrs; i++) {
- (void) memcpy(dest, in->nsc_u.hst.h_addr_list[i],
- in->nsc_u.hst.h_length);
- strs = in->nsc_u.hst.h_length;
- addrlist[i] = dest - offset;
- dest += strs;
- dest = (char *)(((int)dest + 3) & ~3);
- }
-
- addrlist[i] = 0; /* null term ptr chain */
-
- out->nsc_u.hst.h_addr_list = (char **)((int)addrlist-offset);
-
- out->nsc_u.hst.h_length = in->nsc_u.hst.h_length;
- out->nsc_u.hst.h_addrtype = in->nsc_u.hst.h_addrtype;
-
- (void) memcpy(in, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- return (retb);
-
-}
-
-void
-getnode_nam_reaper()
-{
- nsc_reaper("getnode_nam", nnam_hash, &current_admin.node, &node_lock);
-}
-
-void
-getnode_addr_reaper()
-{
- nsc_reaper("getnode_addr", addr_hash, &current_admin.node, &node_lock);
+ipname_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%s:af=%d:flags=%d]",
+ name,
+ argp->key.ipnode.name,
+ argp->key.ipnode.af_family,
+ argp->key.ipnode.flags);
}
diff --git a/usr/src/cmd/nscd/getprinter.c b/usr/src/cmd/nscd/getprinter.c
new file mode 100644
index 0000000000..d5d82fc3c5
--- /dev/null
+++ b/usr/src/cmd/nscd/getprinter.c
@@ -0,0 +1,47 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getprinter* calls in nscd
+ */
+
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+
+#define NSC_NAME_PRINTERS_BYNAME "getprinterbyname"
+
+void
+printer_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_PRINTERS;
+ ctx->file_name = "/etc/printers.conf";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_PRINTERS_BYNAME,
+ NSC_NAME_PRINTERS_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getprof.c b/usr/src/cmd/nscd/getprof.c
index ad171d027c..e7f796a3e1 100644
--- a/usr/src/cmd/nscd/getprof.c
+++ b/usr/src/cmd/nscd/getprof.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,479 +29,18 @@
* Routines to handle getprof* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
+#include "cache.h"
-#include <prof_attr.h>
-
-#include <getxby_door.h>
-#include "server_door.h"
-#include "nscd.h"
-
-extern profstr_t *_getprofnam(const char *, profstr_t *, char *, int, int *);
-
-static hash_t *nam_hash;
-static mutex_t db_lock = DEFAULTMUTEX;
-static waiter_t db_wait;
-
-static void getprof_namekeepalive(int keep, int interval);
-static void update_prof_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-static void getprof_invalidate_unlocked(void);
-
-void
-getprof_init(void)
-{
- nam_hash = make_hash(current_admin.prof.nsc_suggestedsize);
-}
-
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_prof_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(gnam));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
-
-void
-getprof_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.prof.nsc_pos_ttl;
-
- if (slp < 60) {
- slp = 60;
- }
-
- if ((count = current_admin.prof.nsc_keephot) != 0) {
- interval = (slp / 2)/count;
- if (interval == 0) interval = 1;
- sleep(slp * 2 / 3);
- getprof_namekeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
-
-static void
-getprof_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&db_lock);
- operate_hash(nam_hash, do_findgnams, (char *)table);
- mutex_unlock(&db_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETPROFNAM;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
-
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
-
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
-}
-
-
-/*
- * This routine marks all entries as invalid
- *
- */
-
-void
-getprof_invalidate(void)
-{
- mutex_lock(&db_lock);
- getprof_invalidate_unlocked();
- mutex_unlock(&db_lock);
-}
-
-static void
-getprof_invalidate_unlocked(void)
-{
- operate_hash_addr(nam_hash, do_invalidate, (char *)GETPROFNAM);
- current_admin.prof.nsc_invalidate_count++;
-}
-
-void
-getprof_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.prof.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&db_lock);
-
- if (current_admin.prof.nsc_check_files) {
- struct stat buf;
-
- if (stat(PROFATTR_FILENAME, &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getprof_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getprof_lookup: looking for name %s\n",
- in->nsc_u.name);
- }
-
- for (;;) {
- if (attr_strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getprof_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("getprof_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(nam_hash, in->nsc_u.name);
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused =
- sizeof (*out);
- current_admin.prof.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&db_wait, &db_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.prof.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- profstr_t *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.prof.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits =
- ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_prof_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1, in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update...
- * mark to prevent
- * pileups of threads if the name service is hanging....
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&db_lock);
-
- /*
- * Call non-caching version in libnsl.
- */
- p = _getprofnam(in->nsc_u.name, &out->nsc_u.prof,
- out->nsc_u.buff + sizeof (profstr_t),
- bufferspace, &errno);
- saved_errno = errno;
-
- mutex_lock(&db_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
-
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- logit("getprof_lookup: nscd COULDN'T FIND prof_attr name %s\n",
- in->nsc_u.name);
- }
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.prof.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &retb->nsc_data,
- retb->nsc_data.nsc_bufferbytesused);
- update_prof_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getprof_lookup: nscd FOUND prof_attr name %s\n",
- in->nsc_u.name);
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.prof.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
- update_prof_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.prof.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getprof_lookup: found name %s in cache\n",
- in->nsc_u.name);
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.prof.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getprof_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n", retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
- mutex_unlock(&db_lock);
-}
-
-/*ARGSUSED*/
-static void
-update_prof_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */
- free(*old);
- current_admin.prof.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&db_wait, (char **)old);
- }
-
- *old = new;
-
- if ((new != NULL) && (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.prof.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.prof.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.prof.nsc_neg_ttl;
- }
- }
-}
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_bucket_t *retb;
- nsc_return_t *out;
- char *dest;
- int offset;
- int strs;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = attr_strlen(in->nsc_u.prof.name) +
- attr_strlen(in->nsc_u.prof.res1) +
- attr_strlen(in->nsc_u.prof.res2) +
- attr_strlen(in->nsc_u.prof.desc) +
- attr_strlen(in->nsc_u.prof.attr) + PROFATTR_DB_NCOL;
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = strs + ((int)&out->nsc_u.prof - (int)out) +
- sizeof (profstr_t);
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (profstr_t);
- offset = (int)dest;
-
- attr_strcpy(dest, in->nsc_u.prof.name);
- strs = 1 + attr_strlen(in->nsc_u.prof.name);
- out->nsc_u.prof.name = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.prof.res1);
- strs = 1 + attr_strlen(in->nsc_u.prof.res1);
- out->nsc_u.prof.res1 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.prof.res2);
- strs = 1 + attr_strlen(in->nsc_u.prof.res2);
- out->nsc_u.prof.res2 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.prof.desc);
- strs = 1 + attr_strlen(in->nsc_u.prof.desc);
- out->nsc_u.prof.desc = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.prof.attr);
- out->nsc_u.prof.attr = dest - offset;
-
- memcpy(in, out, out->nsc_bufferbytesused);
-
- return (retb);
-}
+#define nam_db ctx->nsc_db[0]
+#define NSC_NAME_PROFATTR_BYNAME "getprofnam"
void
-getprof_reaper(void)
-{
- nsc_reaper("getprof", nam_hash, &current_admin.prof, &db_lock);
+prof_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_PROFATTR;
+ ctx->file_name = "/etc/security/prof_attr";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_PROFATTR_BYNAME,
+ NSC_NAME_PROFATTR_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
}
diff --git a/usr/src/cmd/nscd/getproject.c b/usr/src/cmd/nscd/getproject.c
new file mode 100644
index 0000000000..76ca1e9063
--- /dev/null
+++ b/usr/src/cmd/nscd/getproject.c
@@ -0,0 +1,80 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getproj* calls in nscd
+ */
+
+#include <stdlib.h>
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define pid_db ctx->nsc_db[1]
+
+#define NSC_NAME_PROJECT_BYNAME "getprojbyname"
+#define NSC_NAME_PROJECT_BYID "getprojbyid"
+
+static void projid_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int projid_compar(const void *, const void *);
+static uint_t projid_gethash(nss_XbyY_key_t *, int);
+
+void
+project_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_PROJECT;
+ ctx->file_name = "/etc/project";
+ ctx->db_count = 2;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_PROJECT_BYNAME,
+ NSC_NAME_PROJECT_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+
+ pid_db = make_cache(nsc_key_other,
+ NSS_DBOP_PROJECT_BYID,
+ NSC_NAME_PROJECT_BYID,
+ projid_compar,
+ projid_getlogstr,
+ projid_gethash, nsc_ht_default, -1);
+}
+
+static int
+projid_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ return (_NSC_INT_KEY_CMP(e1->key.projid, e2->key.projid));
+}
+
+static uint_t
+projid_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(&key->projid, sizeof (key->projid), htsize));
+}
+
+static void
+projid_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%d]", name, argp->key.projid);
+}
diff --git a/usr/src/cmd/nscd/getproto.c b/usr/src/cmd/nscd/getproto.c
new file mode 100644
index 0000000000..d7605da680
--- /dev/null
+++ b/usr/src/cmd/nscd/getproto.c
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getprotoby* calls in nscd
+ */
+
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define num_db ctx->nsc_db[1]
+
+#define NSC_NAME_PROTOCOLS_BYNAME "getprotobyname"
+#define NSC_NAME_PROTOCOLS_BYNUMBER "getprotobynumber"
+
+void
+proto_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_PROTOCOLS;
+ ctx->file_name = "/etc/inet/protocols";
+ ctx->db_count = 2;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_PROTOCOLS_BYNAME,
+ NSC_NAME_PROTOCOLS_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+
+ num_db = make_cache(nsc_key_int,
+ NSS_DBOP_PROTOCOLS_BYNUMBER,
+ NSC_NAME_PROTOCOLS_BYNUMBER,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getpw.c b/usr/src/cmd/nscd/getpw.c
index cd38871554..645861e733 100644
--- a/usr/src/cmd/nscd/getpw.c
+++ b/usr/src/cmd/nscd/getpw.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,644 +29,54 @@
* Routines to handle getpw* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <nss_common.h>
-#include <ucred.h>
+#include "cache.h"
-#include "getxby_door.h"
-#include "server_door.h"
-
-#include "nscd.h"
-
-static hash_t *uid_hash;
-static hash_t *nam_hash;
-static mutex_t passwd_lock = DEFAULTMUTEX;
-static waiter_t passwd_wait;
-
-static void getpw_invalidate_unlocked(void);
-static void getpw_namekeepalive(int keep, int interval);
-static void getpw_uidkeepalive(int keep, int interval);
-static void update_pw_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findnams(nsc_bucket_t *ptr, int *table, char *name);
-static void do_finduids(nsc_bucket_t *ptr, int *table, int uid);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-
-void
-getpw_init(void)
-{
- uid_hash = make_ihash(current_admin.passwd.nsc_suggestedsize);
- nam_hash = make_hash(current_admin.passwd.nsc_suggestedsize);
-}
-
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_pw_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_finduids(nsc_bucket_t *ptr, int *table, int uid)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- insertn(table, ptr->nsc_hits, uid);
- }
-}
-
-static void
-do_findnams(nsc_bucket_t *ptr, int *table, char *name)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(name));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
+#define nam_db ctx->nsc_db[0]
+#define uid_db ctx->nsc_db[1]
+#define NSC_NAME_PASSWD_BYNAME "getpwnam"
+#define NSC_NAME_PASSWD_BYUID "getpwuid"
+static void pwuid_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int pwuid_compar(const void *, const void *);
+static uint_t pwuid_gethash(nss_XbyY_key_t *, int);
void
-getpw_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.passwd.nsc_pos_ttl;
-
- if (slp < 60) {
- slp = 60;
- }
-
- if ((count = current_admin.passwd.nsc_keephot) != 0) {
- interval = (slp / 2)/count;
- if (interval == 0) interval = 1;
- sleep(slp * 2 / 3);
- getpw_uidkeepalive(count, interval);
- getpw_namekeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
-
-static void
-getpw_uidkeepalive(int keep, int interval)
-{
- int *table;
- nsc_data_t ping;
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&passwd_lock);
- operate_hash(uid_hash, do_finduids, (char *)table);
- mutex_unlock(&passwd_lock);
-
- for (i = 1; i <= keep; i++) {
- ping.nsc_call.nsc_callnumber = GETPWUID;
- if ((ping.nsc_call.nsc_u.uid = table[keep + 1 + i]) == -1)
- continue; /* unused slot in table */
- launch_update(&ping.nsc_call);
- sleep(interval);
- }
- free(table);
+passwd_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_PASSWD;
+ ctx->file_name = "/etc/passwd";
+ ctx->db_count = 2;
+ ctx->cfg.pos_ttl = 600;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_PASSWD_BYNAME,
+ NSC_NAME_PASSWD_BYNAME,
+ NULL, NULL,
+ NULL, nsc_ht_default, -1);
+
+ uid_db = make_cache(nsc_key_other,
+ NSS_DBOP_PASSWD_BYUID,
+ NSC_NAME_PASSWD_BYUID,
+ pwuid_compar,
+ pwuid_getlogstr,
+ pwuid_gethash, nsc_ht_default, -1);
}
+static int
+pwuid_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
-static void
-getpw_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&passwd_lock);
- operate_hash(nam_hash, do_findnams, (char *)table);
- mutex_unlock(&passwd_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETPWNAM;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
-
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
-
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+ return (_NSC_INT_KEY_CMP(e1->key.uid, e2->key.uid));
}
-
-
-
-/*
- * This routine marks all entries as invalid
- *
- */
-void
-getpw_invalidate(void)
-{
- mutex_lock(&passwd_lock);
- getpw_invalidate_unlocked();
- mutex_unlock(&passwd_lock);
+static uint_t
+pwuid_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (key->uid % htsize);
}
static void
-getpw_invalidate_unlocked(void)
-{
- operate_hash_addr(nam_hash, do_invalidate, (char *)GETPWNAM);
- operate_hash_addr(uid_hash, do_invalidate, (char *)GETPWUID);
- current_admin.passwd.nsc_invalidate_count++;
-}
-
-void
-getpw_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.passwd.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&passwd_lock);
-
- if (current_admin.passwd.nsc_check_files) {
- struct stat buf;
-
- if (stat("/etc/passwd", &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getpw_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
- logit("getpw_lookup: looking for uid %d\n",
- in->nsc_u.uid);
- } else {
- logit("getpw_lookup: looking for name %s\n",
- in->nsc_u.name);
- }
- }
-
- for (;;) {
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
- bucket = get_hash(uid_hash, (char *)in->nsc_u.uid);
- } else { /* make reasonableness check here */
- if (strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getpw_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
-
- logit("getpw_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(nam_hash, in->nsc_u.name);
- }
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.passwd.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&passwd_wait, &passwd_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if (*bucket == NULL ||
- (in->nsc_callnumber & UPDATEBIT) ||
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.passwd.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /*
- * time has expired
- */
- int saved_errno;
- int saved_hits = 0;
- struct passwd *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.passwd.nsc_throttle_count++;
- goto getout;
- }
- if (*bucket != NULL) {
- saved_hits = ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data
- * is non-existent or out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_pw_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1,
- in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing
- * update... mark to prevent pileups of threads if
- * the name service is hanging..
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&passwd_lock);
-
- if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
- p = _uncached_getpwuid_r(in->nsc_u.uid, &out->nsc_u.pwd,
- out->nsc_u.buff+sizeof (struct passwd),
- bufferspace);
- saved_errno = errno;
- } else {
- p = _uncached_getpwnam_r(in->nsc_u.name,
- &out->nsc_u.pwd,
- out->nsc_u.buff+sizeof (struct passwd),
- bufferspace);
- saved_errno = errno;
- }
-
- mutex_lock(&passwd_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETPWUID) {
- logit("getpw_lookup: nscd COULDN'T FIND uid %d\n",
- in->nsc_u.uid);
- } else {
- logit("getpw_lookup: nscd COULDN'T FIND passwd name %s\n",
- in->nsc_u.name);
- }
- }
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.passwd.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &retb->nsc_data,
- retb->nsc_data.nsc_bufferbytesused);
- update_pw_bucket((nsc_bucket_t **)bucket, retb,
- in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETPWUID) {
- logit("getpw_lookup: nscd FOUND uid %d\n",
- in->nsc_u.uid);
- } else {
- logit("getpw_lookup: nscd FOUND passwd name %s\n",
- in->nsc_u.name);
- }
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.passwd.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
- update_pw_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.passwd.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETPWUID) {
- logit("getpw_lookup: found uid %d in cache\n",
- in->nsc_u.uid);
- } else {
- logit("getpw_lookup: found name %s in cache\n",
- in->nsc_u.name);
- }
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.passwd.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- if (MASKUPDATEBIT(in->nsc_callnumber) ==
- GETPWUID) {
- logit("getpw_lookup: %d marked as NOT FOUND in cache.\n",
- in->nsc_u.uid);
- } else {
- logit("getpw_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n",
- retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
-
- mutex_unlock(&passwd_lock);
-
- /*
- * secure mode check - blank out passwd if call sucessfull
- * and caller != effective id
- */
- if ((current_admin.passwd.nsc_secure_mode != 0) &&
- (out->nsc_return_code == SUCCESS) &&
- !(UPDATEBIT & in->nsc_callnumber)) {
-
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- perror("door_ucred");
- } else {
- if (ucred_geteuid(uc) != out->nsc_u.pwd.pw_uid) {
- /*
- * write *NP* into passwd field if
- * not already that way... we fixed
- * the buffer code so there's always room.
- */
- int len;
-
- char *foo = out->nsc_u.buff
- + sizeof (struct passwd)
- + (int)out->nsc_u.pwd.pw_passwd;
-
- len = strlen(foo);
- if (len > 0 &&
- strcmp(foo, "*NP*") != 0 &&
- strcmp(foo, "x") != 0) {
- if (len < 5)
- len = 5;
- strncpy(foo, "*NP*", len);
- /*
- * strncpy will
- * blank all
- */
- }
- }
- ucred_free(uc);
- }
- }
-}
-
-/*ARGSUSED*/
-static void
-update_pw_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) {
- /* old data exists */
- free(*old);
- current_admin.passwd.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&passwd_wait, (char **)old);
- }
-
-
-
- *old = new;
-
- if ((new != NULL) &&
- (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
-
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.passwd.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.passwd.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.passwd.nsc_neg_ttl;
- }
- }
-}
-
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_bucket_t *retb;
- char *dest;
-
- nsc_return_t *out;
- int offset;
- int strs;
- int pwlen;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = 0;
- strs += 1 + strlen(in->nsc_u.pwd.pw_name);
- pwlen = strlen(in->nsc_u.pwd.pw_passwd);
- if (pwlen < 4)
- pwlen = 4;
- strs += 1 + pwlen;
- strs += 1 + strlen(in->nsc_u.pwd.pw_age);
- strs += 1 + strlen(in->nsc_u.pwd.pw_comment);
- strs += 1 + strlen(in->nsc_u.pwd.pw_gecos);
- strs += 1 + strlen(in->nsc_u.pwd.pw_dir);
- strs += 1 + strlen(in->nsc_u.pwd.pw_shell);
-
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
-
-
-
- out->nsc_bufferbytesused = sizeof (*in) + strs;
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
- out->nsc_u.pwd.pw_uid = in->nsc_u.pwd.pw_uid;
- out->nsc_u.pwd.pw_gid = in->nsc_u.pwd.pw_gid;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (struct passwd);
-
- offset = (int)dest;
-
- strcpy(dest, in->nsc_u.pwd.pw_name);
- strs = 1 + strlen(in->nsc_u.pwd.pw_name);
- out->nsc_u.pwd.pw_name = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_passwd);
- strs = 1 + pwlen;
- out->nsc_u.pwd.pw_passwd = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_age);
- strs = 1 + strlen(in->nsc_u.pwd.pw_age);
- out->nsc_u.pwd.pw_age = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_comment);
- strs = 1 + strlen(in->nsc_u.pwd.pw_comment);
- out->nsc_u.pwd.pw_comment = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_gecos);
- strs = 1 + strlen(in->nsc_u.pwd.pw_gecos);
- out->nsc_u.pwd.pw_gecos = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_dir);
- strs = 1 + strlen(in->nsc_u.pwd.pw_dir);
- out->nsc_u.pwd.pw_dir = dest - offset;
- dest += strs;
-
- strcpy(dest, in->nsc_u.pwd.pw_shell);
- out->nsc_u.pwd.pw_shell = dest - offset;
-
- memcpy(in, out, retb->nsc_data.nsc_bufferbytesused);
-
-
- return (retb);
-
-}
-
-void
-getpw_uid_reaper()
-{
- nsc_reaper("getpw_uid", uid_hash, &current_admin.passwd, &passwd_lock);
-}
-
-void
-getpw_nam_reaper()
-{
- nsc_reaper("getpw_nam", nam_hash, &current_admin.passwd, &passwd_lock);
+pwuid_getlogstr(char *name, char *whoami, size_t len, nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%d]", name, argp->key.uid);
}
diff --git a/usr/src/cmd/nscd/getrpc.c b/usr/src/cmd/nscd/getrpc.c
new file mode 100644
index 0000000000..aa62dee73f
--- /dev/null
+++ b/usr/src/cmd/nscd/getrpc.c
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getrpcby* calls in nscd
+ */
+
+#include "cache.h"
+
+#define nam_db ctx->nsc_db[0]
+#define num_db ctx->nsc_db[1]
+
+#define NSC_NAME_RPC_BYNAME "getrpcbyname"
+#define NSC_NAME_RPC_BYNUMBER "getrpcbynumber"
+
+void
+rpc_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_RPC;
+ ctx->file_name = "/etc/rpc";
+ ctx->db_count = 2;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_RPC_BYNAME,
+ NSC_NAME_RPC_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+
+ num_db = make_cache(nsc_key_int,
+ NSS_DBOP_RPC_BYNUMBER,
+ NSC_NAME_RPC_BYNUMBER,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getserv.c b/usr/src/cmd/nscd/getserv.c
new file mode 100644
index 0000000000..700d5c6bfb
--- /dev/null
+++ b/usr/src/cmd/nscd/getserv.c
@@ -0,0 +1,158 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle getserv* calls in nscd
+ */
+
+#include <strings.h>
+#include "cache.h"
+
+
+#define name_db ctx->nsc_db[0]
+#define port_db ctx->nsc_db[1]
+
+#define NSC_NAME_SERVICES_BYNAME "getservbyname"
+#define NSC_NAME_SERVICES_BYPORT "getservbyport"
+
+static void servname_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int servname_compar(const void *, const void *);
+static uint_t servname_gethash(nss_XbyY_key_t *, int);
+
+static void servport_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+static int servport_compar(const void *, const void *);
+static uint_t servport_gethash(nss_XbyY_key_t *, int);
+
+void
+serv_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_SERVICES;
+ ctx->file_name = "/etc/services";
+ ctx->db_count = 2;
+ name_db = make_cache(nsc_key_other,
+ NSS_DBOP_SERVICES_BYNAME,
+ NSC_NAME_SERVICES_BYNAME,
+ servname_compar,
+ servname_getlogstr,
+ servname_gethash, nsc_ht_default, -1);
+
+ port_db = make_cache(nsc_key_other,
+ NSS_DBOP_SERVICES_BYPORT,
+ NSC_NAME_SERVICES_BYPORT,
+ servport_compar,
+ servport_getlogstr,
+ servport_gethash, nsc_ht_default, -1);
+}
+
+static int
+servname_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+
+ /* compare protocol */
+ if (e1->key.serv.proto == NULL && e2->key.serv.proto)
+ return (-1);
+ if (e1->key.serv.proto && e2->key.serv.proto == NULL)
+ return (1);
+ if (e1->key.serv.proto) {
+ l1 = strlen(e1->key.serv.proto);
+ l2 = strlen(e2->key.serv.proto);
+ res = strncmp(e1->key.serv.proto, e2->key.serv.proto,
+ (l1 > l2)?l1:l2);
+ if (res > 0)
+ return (1);
+ if (res < 0)
+ return (-1);
+ }
+
+ /* compare service name */
+ l1 = strlen(e1->key.serv.serv.name);
+ l2 = strlen(e2->key.serv.serv.name);
+ res = strncmp(e1->key.serv.serv.name, e2->key.serv.serv.name,
+ (l1 > l2)?l1:l2);
+ return (_NSC_INT_KEY_CMP(res, 0));
+}
+
+static uint_t
+servname_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (ces_gethash(key->serv.serv.name, htsize));
+}
+
+static void
+servname_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%s, %s]",
+ name,
+ argp->key.serv.serv.name,
+ check_null(argp->key.serv.proto));
+}
+
+static int
+servport_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+
+ /* compare protocol */
+ if (e1->key.serv.proto == NULL && e2->key.serv.proto)
+ return (-1);
+ if (e1->key.serv.proto && e2->key.serv.proto == NULL)
+ return (1);
+ if (e1->key.serv.proto) {
+ l1 = strlen(e1->key.serv.proto);
+ l2 = strlen(e2->key.serv.proto);
+ res = strncmp(e1->key.serv.proto, e2->key.serv.proto,
+ (l1 > l2)?l1:l2);
+ if (res > 0)
+ return (1);
+ if (res < 0)
+ return (-1);
+ }
+
+ /* compare port */
+ return (_NSC_INT_KEY_CMP(e1->key.serv.serv.port,
+ e2->key.serv.serv.port));
+}
+
+static uint_t
+servport_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(&key->serv.serv.port,
+ sizeof (key->serv.serv.port), htsize));
+}
+
+static void
+servport_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+ (void) snprintf(whoami, len, "%s [key=%d, %s]",
+ name,
+ argp->key.serv.serv.port,
+ check_null(argp->key.serv.proto));
+}
diff --git a/usr/src/cmd/nscd/gettnrhdb.c b/usr/src/cmd/nscd/gettnrhdb.c
new file mode 100644
index 0000000000..b42a51b6e8
--- /dev/null
+++ b/usr/src/cmd/nscd/gettnrhdb.c
@@ -0,0 +1,93 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle tsol_getrhbyaddr calls in nscd
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <libtsnet.h>
+#include "cache.h"
+
+#define tsol_rh_db ctx->nsc_db[0]
+
+#define NSC_NAME_TSOL_RH_BYADDR "tsol_getrhbyaddr"
+
+static int tsol_rh_compar(const void *, const void *);
+static uint_t tsol_rh_gethash(nss_XbyY_key_t *, int);
+static void tsol_rh_getlogstr(char *, char *, size_t, nss_XbyY_args_t *);
+
+void
+tnrhdb_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_TSOL_RH;
+ ctx->db_count = 1;
+ ctx->file_name = TNRHDB_PATH;
+
+ tsol_rh_db = make_cache(nsc_key_other,
+ NSS_DBOP_TSOL_RH_BYADDR,
+ NSC_NAME_TSOL_RH_BYADDR,
+ tsol_rh_compar,
+ tsol_rh_getlogstr,
+ tsol_rh_gethash, nsc_ht_default, -1);
+}
+
+static void
+tsol_rh_getlogstr(char *name, char *whoami, size_t len,
+ nss_XbyY_args_t *argp) {
+
+ (void) snprintf(whoami, len, "%s [key=%s, len=%d, addrtype=%d]",
+ name, argp->key.hostaddr.addr, argp->key.hostaddr.len,
+ argp->key.hostaddr.type);
+}
+
+static int
+tsol_rh_compar(const void *n1, const void *n2) {
+ nsc_entry_t *e1, *e2;
+ int res, l1, l2;
+
+ e1 = (nsc_entry_t *)n1;
+ e2 = (nsc_entry_t *)n2;
+
+ if (e1->key.hostaddr.type > e2->key.hostaddr.type)
+ return (1);
+ else if (e1->key.hostaddr.type < e2->key.hostaddr.type)
+ return (-1);
+
+ l1 = strlen(e1->key.hostaddr.addr);
+ l2 = strlen(e2->key.hostaddr.addr);
+ res = strncasecmp(e1->key.hostaddr.addr, e2->key.hostaddr.addr,
+ (l1 > l2)?l1:l2);
+ return (_NSC_INT_KEY_CMP(res, 0));
+}
+
+static uint_t
+tsol_rh_gethash(nss_XbyY_key_t *key, int htsize) {
+ return (db_gethash(key->hostaddr.addr,
+ strlen(key->hostaddr.addr), htsize));
+}
diff --git a/usr/src/cmd/nscd/gettnrhtp.c b/usr/src/cmd/nscd/gettnrhtp.c
new file mode 100644
index 0000000000..e03804d848
--- /dev/null
+++ b/usr/src/cmd/nscd/gettnrhtp.c
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Routines to handle tsol_gettpbyname call in nscd
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <libtsnet.h>
+#include "cache.h"
+
+#define tsol_tp_db ctx->nsc_db[0]
+
+#define NSC_NAME_TSOL_TP_BYNAME "tsol_gettpbyname"
+
+void
+tnrhtp_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = TNRHTP_PATH;
+ ctx->db_count = 1;
+ ctx->file_name = TNRHTP_PATH;
+
+ tsol_tp_db = make_cache(nsc_key_cis,
+ NSS_DBOP_TSOL_TP_BYNAME,
+ NSC_NAME_TSOL_TP_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
+}
diff --git a/usr/src/cmd/nscd/getuser.c b/usr/src/cmd/nscd/getuser.c
index fe654ef070..bd384a76c5 100644
--- a/usr/src/cmd/nscd/getuser.c
+++ b/usr/src/cmd/nscd/getuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,481 +29,18 @@
* Routines to handle getuser* calls in nscd
*/
-#include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/door.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <thread.h>
-#include <unistd.h>
-#include <ucred.h>
-#include <nss_common.h>
+#include "cache.h"
-#include <user_attr.h>
-
-#include <getxby_door.h>
-#include "server_door.h"
-#include "nscd.h"
-
-extern userstr_t *_getusernam(const char *, userstr_t *, char *, int, int *);
-
-static hash_t *nam_hash;
-static mutex_t db_lock = DEFAULTMUTEX;
-static waiter_t db_wait;
-
-static void getuser_namekeepalive(int keep, int interval);
-static void update_user_bucket(nsc_bucket_t **old, nsc_bucket_t *new,
- int callnumber);
-static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen);
-static void do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam);
-static void do_invalidate(nsc_bucket_t **ptr, int callnumber);
-static void getuser_invalidate_unlocked(void);
-
-void
-getuser_init(void)
-{
- nam_hash = make_hash(current_admin.user.nsc_suggestedsize);
-}
-
-static void
-do_invalidate(nsc_bucket_t ** ptr, int callnumber)
-{
- if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) {
- /* leave pending calls alone */
- update_user_bucket(ptr, NULL, callnumber);
- }
-}
-
-static void
-do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam)
-{
-
- /*
- * be careful with ptr - it may be -1 or NULL.
- */
-
- if (ptr != NULL && ptr != (nsc_bucket_t *)-1) {
- char *tmp = (char *)insertn(table, ptr->nsc_hits,
- (int)strdup(gnam));
- if (tmp != (char *)-1)
- free(tmp);
- }
-}
-
-void
-getuser_revalidate(void)
-{
- for (;;) {
- int slp;
- int interval;
- int count;
-
- slp = current_admin.user.nsc_pos_ttl;
-
- if (slp < 60) {
- slp = 60;
- }
-
- if ((count = current_admin.user.nsc_keephot) != 0) {
- interval = (slp / 2)/count;
- if (interval == 0) interval = 1;
- sleep(slp * 2 / 3);
- getuser_namekeepalive(count, interval);
- } else {
- sleep(slp);
- }
- }
-}
-
-static void
-getuser_namekeepalive(int keep, int interval)
-{
- int *table;
- union {
- nsc_data_t ping;
- char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN];
- } u;
-
- int i;
-
- if (!keep)
- return;
-
- table = maken(keep);
- mutex_lock(&db_lock);
- operate_hash(nam_hash, do_findgnams, (char *)table);
- mutex_unlock(&db_lock);
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- u.ping.nsc_call.nsc_callnumber = GETUSERNAM;
-
- if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1)
- continue; /* unused slot in table */
-
- strcpy(u.ping.nsc_call.nsc_u.name, tmp);
-
- launch_update(&u.ping.nsc_call);
- sleep(interval);
- }
-
- for (i = 1; i <= keep; i++) {
- char *tmp;
- if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1)
- free(tmp);
- }
-
- free(table);
-}
-
-
-/*
- * This routine marks all entries as invalid
- *
- */
-
-void
-getuser_invalidate()
-{
- mutex_lock(&db_lock);
- getuser_invalidate_unlocked();
- mutex_unlock(&db_lock);
-}
-
-static void
-getuser_invalidate_unlocked()
-{
- operate_hash_addr(nam_hash, do_invalidate, (char *)GETUSERNAM);
- current_admin.user.nsc_invalidate_count++;
-}
-
-void
-getuser_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
-{
- int out_of_date;
- nsc_bucket_t *retb;
- char **bucket;
-
- static time_t lastmod;
-
- int bufferspace = maxsize - sizeof (nsc_return_t);
-
- if (current_admin.user.nsc_enabled == 0) {
- out->nsc_return_code = NOSERVER;
- out->nsc_bufferbytesused = sizeof (*out);
- return;
- }
-
- mutex_lock(&db_lock);
-
- if (current_admin.user.nsc_check_files) {
- struct stat buf;
-
- if (stat(USERATTR_FILENAME, &buf) < 0) {
- /*EMPTY*/;
- } else if (lastmod == 0) {
- lastmod = buf.st_mtime;
- } else if (lastmod < buf.st_mtime) {
- getuser_invalidate_unlocked();
- lastmod = buf.st_mtime;
- }
- }
-
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getuser_lookup: looking for name %s\n",
- in->nsc_u.name);
- }
-
- for (;;) {
- if (attr_strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
- ucred_t *uc = NULL;
-
- if (door_ucred(&uc) != 0) {
- logit("getuser_lookup: Name too long, "
- "but no user credential: %s\n",
- strerror(errno));
- } else {
- logit("getuser_lookup: Name too long "
- "from pid %d uid %d\n",
- ucred_getpid(uc),
- ucred_getruid(uc));
- ucred_free(uc);
- }
-
- out->nsc_errno = NSS_NOTFOUND;
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- goto getout;
- }
- bucket = get_hash(nam_hash, in->nsc_u.name);
-
- if (*bucket == (char *)-1) { /* pending lookup */
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused =
- sizeof (*out);
- current_admin.user.nsc_throttle_count++;
- goto getout;
- }
- nscd_wait(&db_wait, &db_lock, bucket);
- release_clearance(in->nsc_callnumber);
- continue; /* go back and relookup hash bucket */
- }
- break;
- }
-
- /*
- * check for no name_service mode
- */
-
- if (*bucket == NULL && current_admin.avoid_nameservice) {
- out->nsc_return_code = NOTFOUND;
- out->nsc_bufferbytesused = sizeof (*out);
- } else if ((*bucket == NULL) || /* New entry in name service */
- (in->nsc_callnumber & UPDATEBIT) || /* needs updating */
- (out_of_date = (!current_admin.avoid_nameservice &&
- (current_admin.user.nsc_old_data_ok == 0) &&
- (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
- /* time has expired */
- int saved_errno;
- int saved_hits = 0;
- userstr_t *p;
-
- if (get_clearance(in->nsc_callnumber) != 0) {
- /* no threads available */
- out->nsc_return_code = NOSERVER;
- /* cannot process now */
- out->nsc_bufferbytesused = sizeof (*out);
- current_admin.user.nsc_throttle_count++;
- goto getout;
- }
-
- if (*bucket != NULL) {
- saved_hits =
- ((nsc_bucket_t *)*bucket)->nsc_hits;
- }
-
- /*
- * block any threads accessing this bucket if data is
- * non-existent out of date
- */
-
- if (*bucket == NULL || out_of_date) {
- update_user_bucket((nsc_bucket_t **)bucket,
- (nsc_bucket_t *)-1, in->nsc_callnumber);
- } else {
- /*
- * if still not -1 bucket we are doing update...
- * mark to prevent
- * pileups of threads if the name service is hanging....
- */
- ((nsc_bucket_t *)(*bucket))->nsc_status |=
- ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- }
- mutex_unlock(&db_lock);
-
- /*
- * Call non-caching version in libnsl.
- */
- p = _getusernam(in->nsc_u.name, &out->nsc_u.user,
- out->nsc_u.buff + sizeof (userstr_t),
- bufferspace, &errno);
- saved_errno = errno;
-
- mutex_lock(&db_lock);
-
- release_clearance(in->nsc_callnumber);
-
- if (p == NULL) { /* data not found */
-
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- logit("getuser_lookup: nscd COULDN'T FIND user_attr name %s\n",
- in->nsc_u.name);
- }
-
-
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.user.nsc_neg_cache_misses++;
-
- retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));
-
- retb->nsc_refcount = 1;
- retb->nsc_data.nsc_bufferbytesused =
- sizeof (nsc_return_t);
- retb->nsc_data.nsc_return_code = NOTFOUND;
- retb->nsc_data.nsc_errno = saved_errno;
- memcpy(out, &retb->nsc_data,
- retb->nsc_data.nsc_bufferbytesused);
- update_user_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- goto getout;
- } else {
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getuser_lookup: nscd FOUND user_attr name %s\n",
- in->nsc_u.name);
- }
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.user.nsc_pos_cache_misses++;
-
- retb = fixbuffer(out, bufferspace);
- update_user_bucket((nsc_bucket_t **)bucket,
- retb, in->nsc_callnumber);
- if (saved_hits)
- retb->nsc_hits = saved_hits;
- }
- } else { /* found entry in cache */
- retb = (nsc_bucket_t *)*bucket;
-
- retb->nsc_hits++;
-
- memcpy(out, &(retb->nsc_data),
- retb->nsc_data.nsc_bufferbytesused);
-
- if (out->nsc_return_code == SUCCESS) {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.user.nsc_pos_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getuser_lookup: found name %s in cache\n",
- in->nsc_u.name);
- }
- } else {
- if (!(UPDATEBIT & in->nsc_callnumber))
- current_admin.user.nsc_neg_cache_hits++;
- if (current_admin.debug_level >= DBG_ALL) {
- logit("getuser_lookup: %s marked as NOT FOUND in cache.\n",
- in->nsc_u.name);
- }
- }
-
- if ((retb->nsc_timestamp < now) &&
- !(in->nsc_callnumber & UPDATEBIT) &&
- !(retb->nsc_status & ST_UPDATE_PENDING)) {
- logit("launch update since time = %d\n", retb->nsc_timestamp);
- retb->nsc_status |= ST_UPDATE_PENDING;
- /* cleared by deletion of old data */
- launch_update(in);
- }
- }
-
-getout:
- mutex_unlock(&db_lock);
-}
-
-/*ARGSUSED*/
-static void
-update_user_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber)
-{
- if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */
- free(*old);
- current_admin.user.nsc_entries--;
- }
-
- /*
- * we can do this before reseting *old since we're holding the lock
- */
-
- else if (*old == (nsc_bucket_t *)-1) {
- nscd_signal(&db_wait, (char **)old);
- }
-
- *old = new;
-
- if ((new != NULL) &&
- (new != (nsc_bucket_t *)-1)) {
- /* real data, not just update pending or invalidate */
- new->nsc_hits = 1;
- new->nsc_status = 0;
- new->nsc_refcount = 1;
- current_admin.user.nsc_entries++;
-
- if (new->nsc_data.nsc_return_code == SUCCESS) {
- new->nsc_timestamp = time(NULL) +
- current_admin.user.nsc_pos_ttl;
- } else {
- new->nsc_timestamp = time(NULL) +
- current_admin.user.nsc_neg_ttl;
- }
- }
-}
-
-/*ARGSUSED*/
-static nsc_bucket_t *
-fixbuffer(nsc_return_t *in, int maxlen)
-{
- nsc_bucket_t *retb;
- nsc_return_t *out;
- char *dest;
- int offset;
- int strs;
-
- /*
- * find out the size of the data block we're going to need
- */
-
- strs = attr_strlen(in->nsc_u.user.name) +
- attr_strlen(in->nsc_u.user.qualifier) +
- attr_strlen(in->nsc_u.user.res1) +
- attr_strlen(in->nsc_u.user.res2) +
- attr_strlen(in->nsc_u.user.attr) + USERATTR_DB_NCOL;
-
- /*
- * allocate it and copy it in
- * code doesn't assume packing order in original buffer
- */
-
- if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) {
- return (NULL);
- }
-
- out = &(retb->nsc_data);
- out->nsc_bufferbytesused = strs + ((int)&out->nsc_u.user - (int)out) +
- sizeof (userstr_t);
- out->nsc_return_code = SUCCESS;
- out->nsc_errno = 0;
-
- dest = retb->nsc_data.nsc_u.buff + sizeof (userstr_t);
- offset = (int)dest;
-
- attr_strcpy(dest, in->nsc_u.user.name);
- strs = 1 + attr_strlen(in->nsc_u.user.name);
- out->nsc_u.user.name = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.user.qualifier);
- strs = 1 + attr_strlen(in->nsc_u.user.qualifier);
- out->nsc_u.user.qualifier = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.user.res1);
- strs = 1 + attr_strlen(in->nsc_u.user.res1);
- out->nsc_u.user.res1 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.user.res2);
- strs = 1 + attr_strlen(in->nsc_u.user.res2);
- out->nsc_u.user.res2 = dest - offset;
- dest += strs;
-
- attr_strcpy(dest, in->nsc_u.user.attr);
- out->nsc_u.user.attr = dest - offset;
-
- memcpy(in, out, out->nsc_bufferbytesused);
-
- return (retb);
-}
+#define nam_db ctx->nsc_db[0]
+#define NSC_NAME_USERATTR_BYNAME "getusernam"
void
-getuser_reaper(void)
-{
- nsc_reaper("getuser", nam_hash, &current_admin.user, &db_lock);
+user_init_ctx(nsc_ctx_t *ctx) {
+ ctx->dbname = NSS_DBNAM_USERATTR;
+ ctx->file_name = "/etc/user_attr";
+ ctx->db_count = 1;
+ nam_db = make_cache(nsc_key_ces,
+ NSS_DBOP_USERATTR_BYNAME,
+ NSC_NAME_USERATTR_BYNAME,
+ NULL, NULL, NULL, nsc_ht_default, -1);
}
diff --git a/usr/src/cmd/nscd/hash.c b/usr/src/cmd/nscd/hash.c
deleted file mode 100644
index 91a3018cbb..0000000000
--- a/usr/src/cmd/nscd/hash.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <synch.h>
-#include <memory.h>
-#include <getxby_door.h>
-
-static int hash_string();
-
-hash_t *
-make_hash(size)
-int size;
-{
- hash_t *ptr;
-
- ptr = (hash_t *)malloc(sizeof (*ptr));
- ptr->size = size;
- ptr->table = (hash_entry_t **)
- malloc((unsigned) (sizeof (hash_entry_t *) * size));
- (void) memset((char *)ptr->table, (char)0,
- sizeof (hash_entry_t *)*size);
- ptr->start = NULL;
- ptr->hash_type = String_Key;
- return (ptr);
-}
-
-hash_t *
-make_ihash(size)
-int size;
-{
- hash_t *ptr;
-
- ptr = (hash_t *)malloc(sizeof (*ptr));
- ptr->size = size;
- ptr->table = (hash_entry_t **)malloc((unsigned)
- (sizeof (hash_entry_t *) * size));
- (void) memset((char *)ptr->table, (char)0,
- sizeof (hash_entry_t *)*size);
- ptr->start = NULL;
- ptr->hash_type = Integer_Key;
- return (ptr);
-}
-
-
-char **
-get_hash(hash_t *tbl, char *key)
-{
-
- int bucket;
- hash_entry_t *tmp;
- hash_entry_t *new;
-
- if (tbl->hash_type == String_Key) {
- tmp = tbl->table[bucket = hash_string(key, tbl->size)];
- } else {
- tmp = tbl->table[bucket = abs((int)key) % tbl->size];
- }
-
- if (tbl->hash_type == String_Key) {
- while (tmp != NULL) {
- if (strcmp(tmp->key, key) == 0) {
- return (&tmp->data);
- }
- tmp = tmp->next_entry;
- }
- } else {
- while (tmp != NULL) {
- if (tmp->key == key) {
- return (&tmp->data);
- }
- tmp = tmp->next_entry;
- }
- }
-
- /*
- * not found....
- * insert new entry into bucket...
- */
-
- new = (hash_entry_t *)malloc(sizeof (*new));
- new->key = ((tbl->hash_type == String_Key)?strdup(key):key);
- /*
- * hook into chain from tbl...
- */
- new->right_entry = NULL;
- new->left_entry = tbl->start;
- tbl->start = new;
- if (new->left_entry != NULL)
- new->left_entry->right_entry = new;
- /*
- * hook into bucket chain
- */
- new->next_entry = tbl->table[bucket];
- tbl->table[bucket] = new;
- new->data = NULL; /* so we know that it is new */
- return (&new->data);
-}
-
-char **
-find_hash(hash_t *tbl, char *key)
-{
- hash_entry_t *tmp;
-
- if (tbl->hash_type == String_Key) {
- tmp = tbl->table[hash_string(key, tbl->size)];
- for (; tmp != NULL; tmp = tmp->next_entry) {
- if (strcmp(tmp->key, key) == 0) {
- return (&tmp->data);
- }
- }
- } else {
- tmp = tbl->table[abs((int)key) % tbl->size];
- for (; tmp != NULL; tmp = tmp->next_entry) {
- if (tmp->key == key) {
- return (&tmp->data);
- }
- }
- }
-
- return (NULL);
-}
-
-char *
-del_hash(hash_t *tbl, hash_entry_t *del_this, hash_entry_t *prev, int bucket)
-{
- /*
- * del_this points to entry marked for deletion, prev to
- * item preceeding in bucket chain or NULL if del_this is first.
- * remove from bucket chain first....
- */
- if (tbl->hash_type == String_Key) {
- free(del_this->key);
- }
- if (prev != NULL) {
- prev->next_entry = del_this->next_entry;
- } else {
- tbl->table[bucket] = del_this->next_entry;
- }
- /*
- * now remove from tbl chain....
- */
- if (del_this->right_entry != NULL) { /* not first in chain.... */
- del_this->right_entry->left_entry = del_this->left_entry;
- } else {
- tbl->start = del_this->left_entry;
- }
- if (del_this->left_entry != NULL) { /* not last in chain.... */
- del_this->left_entry->right_entry = del_this->right_entry;
- }
- return (del_this->data);
-}
-
-int
-operate_hash(hash_t *tbl, void (*ptr)(), char *usr_arg)
-{
- hash_entry_t *tmp = tbl->start;
- int c = 0;
-
- while (tmp) {
- (*ptr)(tmp->data, usr_arg, tmp->key);
- tmp = tmp->left_entry;
- c++;
- }
- return (c);
-}
-
-int
-operate_hash_addr(hash_t *tbl, void (*ptr)(), char *usr_arg)
-{
- hash_entry_t *tmp = tbl->start;
- int c = 0;
-
- while (tmp) {
- (*ptr)(&(tmp->data), usr_arg, tmp->key);
- tmp = tmp->left_entry;
- c++;
- }
- return (c);
-}
-
-void
-destroy_hash(hash_t *tbl, int (*ptr)(), char *usr_arg)
-{
- hash_entry_t *tmp = tbl->start, *prev;
-
- while (tmp) {
- if (ptr) {
- (*ptr)(tmp->data, usr_arg, tmp->key);
- }
-
- if (tbl->hash_type == String_Key) {
- free(tmp->key);
- }
- prev = tmp;
- tmp = tmp->left_entry;
- free((char *)prev);
- }
- free((char *)tbl->table);
- free(tbl);
-}
-
-static int
-hash_string(char *s, int modulo)
-{
- unsigned result = 0;
- int i = 1;
-
- while (*s != 0) {
- result += (*s++ << i++);
- }
-
- return (result % modulo);
-}
-
-int
-reap_hash(hash_t *tbl, nsc_stat_t *admin_ptr, mutex_t *hash_lock,
- int howlong)
-{
-
- hash_entry_t *tmp, *next, *prev;
- uint_t count = 0;
- uint_t bucket;
- uint_t extra_sleep = 1;
- uint_t buckets_per_interval, seconds_per_interval, buckets_togo;
- uint_t total_buckets;
- time_t now;
-
- /*
- * We don't want to spend too much time reaping nor too little.
- * We cap the TTL at 2^28 to prevent overflow. This is 8.5 years,
- * so we aren't really going to reap anything anyway.
- * Also, we want the total time to be one second more than the
- * time to expire the entries.
- */
- howlong++;
- if (howlong < 32) howlong = 32;
- if (howlong > (1<<28)) howlong = 1<<28;
-
- /* Total_buckets can range from 37 to 2^30 */
- total_buckets = admin_ptr->nsc_suggestedsize;
-
- if (total_buckets >= howlong && total_buckets > (howlong>>2)) {
- /*
- * In the realm of buckets_per_second. total_buckets might
- * be near 2^30, so we divide first
- */
- buckets_per_interval = total_buckets/(howlong>>2);
- seconds_per_interval = 4;
- } else if (total_buckets >= howlong) {
- /* Still buckets per second, but it is safe to multiply first */
- buckets_per_interval = (total_buckets<<2)/howlong;
- seconds_per_interval = 4;
- } else if (total_buckets <= (howlong>>2)) {
- /*
- * Now in the secs/buck realm. Howlong is at least 4 times
- * total_buckets, so we are safe to use this as the interval.
- * Figure out the rounding error and sleep it at the end.
- */
- seconds_per_interval = howlong/total_buckets;
- buckets_per_interval = 1;
- extra_sleep = 1 + howlong -
- (total_buckets*seconds_per_interval);
- } else {
- /*
- * Still in secs/buck realm, but seconds_per_interval
- * is too short. Use 8 as the minimum, then adjust the extra
- * at the end. We need 8 because of rounding error.
- */
- seconds_per_interval = (howlong/(total_buckets>>3));
- buckets_per_interval = 8;
- extra_sleep = 1 + howlong -
- ((total_buckets>>3)*seconds_per_interval);
- }
-
- /*
- * bucket keeps track of which bucket in the whole table we are on.
- * buckets_togo is which bucket in this interval we are on.
- */
-
- for (bucket = buckets_togo = 0;
- bucket < admin_ptr->nsc_suggestedsize;
- bucket++) {
- if (buckets_togo <= 0) {
- sleep(seconds_per_interval);
- buckets_togo = buckets_per_interval;
- now = time(NULL);
- }
- mutex_lock(hash_lock);
- tmp = tbl->table[bucket];
- prev = NULL;
- while (tmp != NULL) {
- next = tmp->next_entry;
- if (tmp->data == (char *)NULL) {
- del_hash(tbl, tmp, prev, bucket);
- free(tmp);
- count++;
- } else if ((tmp->data != (char *)-1) &&
- ((((nsc_bucket_t *)(tmp->data))->nsc_status &
- ST_UPDATE_PENDING) == 0) &&
- (((nsc_bucket_t *)(tmp->data))->nsc_timestamp
- < now)) {
- del_hash(tbl, tmp, prev, bucket);
- free(tmp->data);
- free(tmp);
- count++;
- admin_ptr->nsc_entries--;
- } else {
- prev = tmp;
- }
- tmp = next;
- }
- mutex_unlock(hash_lock);
- buckets_togo--;
-
- }
- sleep(extra_sleep);
- return (count);
-}
diff --git a/usr/src/cmd/nscd/name-service-cache.xml b/usr/src/cmd/nscd/name-service-cache.xml
index 14cc588eff..e85f22278c 100644
--- a/usr/src/cmd/nscd/name-service-cache.xml
+++ b/usr/src/cmd/nscd/name-service-cache.xml
@@ -1,15 +1,14 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2006 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
The contents of this file are subject to the terms of the
- Common Development and Distribution License, Version 1.0 only
- (the "License"). You may not use this file except in compliance
- with the License.
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
or http://www.opensolaris.org/os/licensing.
@@ -86,6 +85,18 @@
value='solaris.smf.manage.name-service-cache' />
</property_group>
+ <property_group name='config' type='application' >
+ <propval
+ name='enable_per_user_lookup'
+ type='boolean'
+ value='true' />
+ <propval
+ name='per_user_nscd_time_to_live'
+ type='integer'
+ value='120' />
+ </property_group>
+
+
<stability value='Unstable' />
diff --git a/usr/src/cmd/nscd/nscd.h b/usr/src/cmd/nscd/nscd.h
deleted file mode 100644
index a7dab9fd90..0000000000
--- a/usr/src/cmd/nscd/nscd.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _NSCD_H
-#define _NSCD_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern admin_t current_admin;
-
-extern int attr_strlen(char *);
-extern char *attr_strcpy(char *, char *);
-
-extern nsc_stat_t *getcacheptr(char *s);
-extern int nscd_set_lf(admin_t *ptr, char *s);
-extern void logit(char *format, ...);
-extern int launch_update(nsc_call_t *in);
-extern int load_admin_defaults(admin_t *ptr, int will_become_server);
-extern void getpw_init(void);
-extern void getpw_revalidate(void);
-extern void getpw_uid_reaper(void);
-extern void getpw_nam_reaper(void);
-extern void getpw_invalidate(void);
-extern void getpw_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern void getgr_init(void);
-extern void getgr_revalidate(void);
-extern void getgr_uid_reaper(void);
-extern void getgr_nam_reaper(void);
-extern void getgr_invalidate(void);
-extern void getgr_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern void gethost_init(void);
-extern void gethost_revalidate(void);
-extern void gethost_nam_reaper(void);
-extern void gethost_addr_reaper(void);
-extern void gethost_invalidate(void);
-extern void gethost_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern void getnode_init(void);
-extern void getnode_revalidate(void);
-extern void getnode_nam_reaper(void);
-extern void getnode_addr_reaper(void);
-extern void getnode_invalidate(void);
-extern void getnode_name_invalidate(void);
-extern void getnode_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern hash_t *make_hash(int size);
-extern hash_t *make_ihash(int size);
-extern char **get_hash(hash_t *tbl, char *key);
-extern char **find_hash(hash_t *tbl, char *key);
-extern char *del_hash(hash_t *tbl, hash_entry_t *del_this, hash_entry_t *prev,
- int bucket);
-extern int operate_hash(hash_t *tbl, void (*ptr)(), char *usr_arg);
-extern int operate_hash_addr(hash_t *tbl, void (*ptr)(), char *usr_arg);
-extern void nsc_reaper(char *tbl_name, hash_t *tbl,
- nsc_stat_t *admin_ptr, mutex_t *hash_lock);
-extern int reap_hash(hash_t *tbl, nsc_stat_t *admin_ptr,
- mutex_t *hash_lock, int howlong);
-extern void destroy_hash(hash_t *tbl, int (*ptr)(), char *usr_arg);
-extern int *maken(int n);
-extern int insertn(int *table, int n, int data);
-extern int nscd_parse(char *progname, char *filename);
-extern int nscd_set_dl(admin_t *ptr, int value);
-extern int nscd_set_ec(nsc_stat_t *cache, char *name, int value);
-extern int nscd_set_khc(nsc_stat_t *cache, char *name, int value);
-extern int nscd_set_odo(nsc_stat_t *cache, char *name, int value);
-extern int nscd_set_ss(nsc_stat_t *cache, char *name, int value);
-extern int nscd_set_ttl_positive(nsc_stat_t *cache, char *name, int value);
-extern int nscd_set_ttl_negative(nsc_stat_t *cache, char *name, int value);
-extern int nscd_wait(waiter_t *wchan, mutex_t *lock, char **key);
-extern int nscd_signal(waiter_t *wchan, char **key);
-extern int get_clearance(int callnumber);
-extern int release_clearance(int callnumber);
-
-extern void getexec_init(void);
-extern void getexec_revalidate(void);
-extern void getexec_reaper(void);
-extern void getexec_invalidate(void);
-extern void getexec_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern void getprof_init(void);
-extern void getprof_revalidate(void);
-extern void getprof_reaper(void);
-extern void getprof_invalidate(void);
-extern void getprof_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-extern void getuser_init(void);
-extern void getuser_revalidate(void);
-extern void getuser_reaper(void);
-extern void getuser_invalidate(void);
-extern void getuser_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in,
- time_t now);
-
-extern void leave(int n);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _NSCD_H */
diff --git a/usr/src/cmd/nscd/nscd_access.c b/usr/src/cmd/nscd/nscd_access.c
new file mode 100644
index 0000000000..36f168652b
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_access.c
@@ -0,0 +1,588 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nscd_db.h"
+#include "nscd_log.h"
+
+/*
+ * Access control structure for a piece of nscd data. This structure
+ * is always tagged before the nscd data. nscd_alloc, which should
+ * be used to allocate memory that requires access control or usage
+ * count control, will initialize this access control structure at the
+ * start of the memory returned to the caller.
+ */
+struct nscd_access_s {
+ void *data; /* addr of real data */
+ void (*free_func)(nscd_acc_data_t *data); /* destructor */
+ mutex_t mutex; /* protect this structure */
+ mutex_t *data_mutex;
+ rwlock_t *data_rwlock;
+ cond_t *data_cond;
+ int nUse; /* usage count */
+ int type;
+ int delete; /* no longer available */
+ nscd_seq_num_t seq_num; /* sequence number */
+};
+
+/* size should be in multiple of 8 */
+static int sizeof_access = roundup(sizeof (nscd_access_t));
+
+#define ABORT_DUE_TO_NO_VALID_NSCD_ACCESS_DATA 0
+#define ASSERT_ACCESS_DATA \
+ if (access->data != data) \
+ assert(ABORT_DUE_TO_NO_VALID_NSCD_ACCESS_DATA)
+
+#define SET_ACCESS_PTR \
+ access = (nscd_access_t *) \
+ ((void *)((char *)data - sizeof_access))
+
+static void _nscd_free(nscd_acc_data_t *data);
+
+/*
+ * FUNCTION: _nscd_release
+ *
+ * Decrements the usage count maintained in the access data
+ * tagged before 'data'. Delete the nscd data item if the delete
+ * flag is set and the usage count reaches 0.
+ */
+void
+_nscd_release(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_release";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p, "
+ "seq = %lld, nUse = %d\n",
+ data, access->data, access->seq_num, access->nUse);
+ ASSERT_ACCESS_DATA;
+
+ (void) mutex_lock(&access->mutex);
+ access->nUse--;
+ if (access->nUse < 0) {
+#define ACCESS_NUSE_LESS_THAN_ZERO 0
+ assert(ACCESS_NUSE_LESS_THAN_ZERO);
+ }
+ if (access->nUse <= 0 &&
+ access->delete == 1) {
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "deleting data %p\n", access->data);
+ (access->free_func)(access->data);
+
+ /*
+ * if we get here, no other thread could be
+ * holding the access->mutex lock, It is safe
+ * to free the memory containing the mutex
+ * structure. No mutex_unlock is necessary.
+ */
+ _nscd_free(data);
+ } else
+ (void) mutex_unlock(&access->mutex);
+}
+
+
+/*
+ * FUNCTION: _nscd_destroy
+ *
+ * Marks the nscd data item as to-be-deleted and then releases
+ * (If the usage count happens to be zero, then _nscd_release()
+ * will destroy the data.)
+ *
+ * Note that _nscd_destroy should only be called if the
+ * caller has created the nscd data with _nscd_alloc
+ * (with the exception of _nscd_set). That nscd data
+ * item should be private to the caller.
+ */
+static void
+_nscd_destroy(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_destroy";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ (void) mutex_lock(&access->mutex);
+ access->delete = 1;
+ (void) mutex_unlock(&access->mutex);
+
+ _nscd_release(data);
+}
+
+/*
+ * FUNCTION: _nscd_get
+ *
+ * Increment the usage count by one if 'data' can
+ * be found in the internal address database.
+ */
+nscd_acc_data_t *
+_nscd_get(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ void *ret = data;
+ rwlock_t *addr_rwlock;
+ char *me = "_nscd_get";
+
+ if (data == NULL)
+ return (NULL);
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p, seq#= %lld, nUse = %d\n",
+ data, access->data, access->seq_num, access->nUse);
+ ASSERT_ACCESS_DATA;
+
+ /*
+ * see if this addr is still valid,
+ * if so, _nscd_is_int_addr will
+ * do a read lock on the returned
+ * multiple readers/single writer lock
+ * to prevent the access data from being
+ * deleted while it is being accessed.
+ */
+ if ((addr_rwlock = _nscd_is_int_addr(data,
+ access->seq_num)) == NULL) {
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "internal address %p not found\n", data);
+ assert(addr_rwlock != NULL);
+ return (NULL);
+ }
+
+ (void) mutex_lock(&access->mutex);
+ if (access->delete == 1)
+ ret = NULL;
+ else
+ access->nUse++;
+ (void) mutex_unlock(&access->mutex);
+
+ /*
+ * done with the multiple readers/single writer lock
+ */
+ (void) rw_unlock(addr_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_set
+ *
+ * _nscd_set sets the address of a nscd data item
+ * to 'new' and delete the old nscd data (old).
+ * The pointer 'new' is returned.
+ */
+nscd_acc_data_t *
+_nscd_set(
+ nscd_acc_data_t *old,
+ nscd_acc_data_t *new)
+{
+ nscd_acc_data_t *old_data, *new_data;
+ char *me = "_nscd_set";
+
+ if (new == old)
+ return (old);
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new = %p, old = %p\n", new, old);
+
+ old_data = _nscd_get(old);
+ new_data = _nscd_get(new);
+
+ if (old_data != new_data) {
+
+ _nscd_destroy(old_data);
+ _nscd_release(new_data);
+ return (new_data);
+ }
+
+ /* if old_data == new_data, both must be NULL */
+ return (NULL);
+}
+
+/*
+ * FUNCTION: _nscd_rdlock
+ *
+ * Lock (rw_rdlock) a nscd data item for reading. The caller
+ * needs to call _nscd_rw_unlock() to unlock the data item
+ * when done using the data.
+ */
+nscd_acc_data_t *
+_nscd_rdlock(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ void *ret;
+ char *me = "_nscd_rdlock";
+
+ ret = _nscd_get(data);
+
+ if (ret == NULL)
+ return (NULL);
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_rwlock != NULL);
+
+ (void) rw_rdlock(access->data_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_wrlock
+ *
+ * Lock (rw_wrlock) a nscd data item for writing. The caller
+ * needs to call _nscd_rw_unlock() to unlock the data item
+ * when done using the data.
+ */
+nscd_acc_data_t *
+_nscd_wrlock(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ void *ret;
+ char *me = "_nscd_wrlock";
+
+ ret = _nscd_get(data);
+
+ if (ret == NULL)
+ return (NULL);
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_rwlock != NULL);
+
+ (void) rw_wrlock(access->data_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_rw_unlock
+ *
+ * Unlock (rw_unlock) a locked nscd data item.
+ */
+void
+_nscd_rw_unlock(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_rw_unlock";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n",
+ data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_rwlock != NULL);
+
+ (void) rw_unlock(access->data_rwlock);
+ _nscd_release(data);
+}
+
+/*
+ * FUNCTION: _nscd_rw_unlock_no_release
+ *
+ * Unlock (rw_unlock) a locked nscd data item but without release
+ * it, i.e., without decrement the usage count to indicate that
+ * the data item is still being referenced.
+ */
+void
+_nscd_rw_unlock_no_release(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_rwlock != NULL);
+
+ (void) rw_unlock(access->data_rwlock);
+}
+
+/*
+ * FUNCTION: _nscd_mutex_lock
+ *
+ * Lock (mutex_lock) a nscd data item. The caller needs
+ * to call _nscd_mutex_unlock() to unlock the data item
+ * when done using the data.
+ */
+nscd_acc_data_t *
+_nscd_mutex_lock(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ void *ret;
+ char *me = "_nscd_mutex_lock";
+
+ ret = _nscd_get(data);
+
+ if (ret == NULL)
+ return (NULL);
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_mutex != NULL);
+
+ (void) mutex_lock(access->data_mutex);
+
+ return (ret);
+}
+
+
+/*
+ * FUNCTION: _nscd_mutex_unlock
+ *
+ * Unlock a locked nscd data item (that were locked by _nscd_mutex_lock)..
+ */
+void
+_nscd_mutex_unlock(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_mutex_unlock";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_mutex != NULL);
+
+ (void) mutex_unlock(access->data_mutex);
+ _nscd_release(data);
+}
+
+/*
+ * FUNCTION: _nscd_cond_wait
+ *
+ * Perform a condition wait with the cond_t and mutex_t associated
+ * with data.
+ */
+void
+_nscd_cond_wait(
+ nscd_acc_data_t *data, cond_t *cond)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_cond_wait";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_cond != NULL && access->data_mutex != NULL);
+
+ if (cond == NULL)
+ (void) cond_wait(access->data_cond, access->data_mutex);
+ else
+ (void) cond_wait(cond, access->data_mutex);
+}
+
+/*
+ * FUNCTION: _nscd_cond_signal
+ *
+ * Perform a condition signal with the cond_t associated with 'data'.
+ */
+void
+_nscd_cond_signal(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+ char *me = "_nscd_cond_signal";
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+
+ _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
+ (me, "data = %p, access->data = %p\n", data, access->data);
+ ASSERT_ACCESS_DATA;
+
+ assert(access->data_cond != NULL);
+
+ (void) cond_signal(access->data_cond);
+}
+
+/*
+ * FUNCTION: _nscd_alloc
+ *
+ * Allocate a piece of nscd memory. 'data_free'
+ * is the function to invoke to free the data
+ * stored in this memory, i.e., the desctrctor.
+ * 'option' indicate whether a mutex or a
+ * readers/writer (or both, or none) should also
+ * be allocated.
+ */
+nscd_acc_data_t *
+_nscd_alloc(
+ int type,
+ size_t size,
+ void (*data_free)(nscd_acc_data_t *data),
+ int option)
+{
+ nscd_access_t *access;
+ nscd_acc_data_t *ptr;
+ nscd_seq_num_t seq_num;
+ rwlock_t *rwlock = NULL;
+ mutex_t *mutex = NULL;
+ cond_t *cond = NULL;
+
+ if ((ptr = (nscd_acc_data_t *)calloc(1,
+ size + sizeof_access)) == NULL)
+ return (NULL);
+ if (option & NSCD_ALLOC_MUTEX) {
+ if ((mutex = (mutex_t *)calloc(1, sizeof (mutex_t))) ==
+ NULL) {
+ free(ptr);
+ return (NULL);
+ } else
+ (void) mutex_init(mutex, USYNC_THREAD, NULL);
+ }
+ if (option & NSCD_ALLOC_RWLOCK) {
+ if ((rwlock = (rwlock_t *)calloc(1, sizeof (rwlock_t))) ==
+ NULL) {
+ free(ptr);
+ free(mutex);
+ return (NULL);
+ } else
+ (void) rwlock_init(rwlock, USYNC_THREAD, NULL);
+ }
+ if (option & NSCD_ALLOC_COND) {
+ if ((cond = (cond_t *)calloc(1, sizeof (cond_t))) ==
+ NULL) {
+ free(ptr);
+ free(mutex);
+ free(rwlock);
+ return (NULL);
+ } else
+ (void) cond_init(cond, USYNC_THREAD, NULL);
+ }
+
+ /* get current sequence number */
+ seq_num = _nscd_get_seq_num();
+
+ access = (nscd_access_t *)ptr;
+ access->data = (char *)ptr + sizeof_access;
+ access->data_mutex = mutex;
+ access->data_rwlock = rwlock;
+ access->data_cond = cond;
+ access->nUse = 0;
+ access->delete = 0;
+ access->type = type;
+ access->free_func = data_free;
+ access->seq_num = seq_num;
+
+ /* add the address to the internal address database */
+ if (_nscd_add_int_addr(access->data, type,
+ seq_num) != NSCD_SUCCESS) {
+ free(ptr);
+ return (NULL);
+ }
+
+ return (access->data);
+}
+
+/*
+ * FUNCTION: _nscd_free
+ *
+ * Free a piece of nscd memory.
+ */
+static void
+_nscd_free(
+ nscd_acc_data_t *data)
+{
+ nscd_access_t *access;
+
+ if (data == NULL)
+ return;
+
+ SET_ACCESS_PTR;
+ ASSERT_ACCESS_DATA;
+
+ /* remove the address from the internal address database */
+ _nscd_del_int_addr(access->data, access->seq_num);
+
+ if (access->data_mutex)
+ free(access->data_mutex);
+ if (access->data_rwlock)
+ free(access->data_rwlock);
+ if (access->data_cond)
+ free(access->data_cond);
+
+ (void) memset(access, 0, sizeof (*access));
+
+ free(access);
+}
diff --git a/usr/src/cmd/nscd/nscd_admin.c b/usr/src/cmd/nscd/nscd_admin.c
new file mode 100644
index 0000000000..5574e88744
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_admin.c
@@ -0,0 +1,410 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+#include "cache.h"
+#include "nscd_door.h"
+#include "nscd_log.h"
+#include "nscd_admin.h"
+
+extern nsc_ctx_t *cache_ctx_p[];
+extern char *cache_name[];
+
+static nscd_admin_t admin_c = { 0 };
+static nscd_admin_mod_t admin_mod = { 0 };
+static mutex_t mod_lock = DEFAULTMUTEX;
+
+/*ARGSUSED*/
+int
+_nscd_door_getadmin(void *outbuf)
+{
+ int i;
+ int data_size = NSCD_N2N_DOOR_BUF_SIZE(admin_c);
+ nss_pheader_t *phdr = (nss_pheader_t *)outbuf;
+ nscd_cfg_cache_t cfg_default = NSCD_CFG_CACHE_DEFAULTS;
+
+ /*
+ * if size of buffer is not big enough, tell the caller to
+ * increase it to the size returned
+ */
+ if (phdr->pbufsiz < data_size)
+ return (sizeof (admin_c));
+
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ phdr->data_off = sizeof (nss_pheader_t);
+ phdr->data_len = sizeof (admin_c);
+
+ for (i = 0; i < CACHE_CTX_COUNT; i++) {
+ if (cache_ctx_p[i] != NULL) {
+ (void) rw_rdlock(&cache_ctx_p[i]->cfg_rwlp);
+ admin_c.cache_cfg[i] = cache_ctx_p[i]->cfg;
+ (void) rw_unlock(&cache_ctx_p[i]->cfg_rwlp);
+
+ (void) mutex_lock(&cache_ctx_p[i]->stats_mutex);
+ admin_c.cache_stats[i] = cache_ctx_p[i]->stats;
+ (void) mutex_unlock(&cache_ctx_p[i]->stats_mutex);
+ } else {
+ admin_c.cache_cfg[i] = cfg_default;
+ (void) memset(&admin_c.cache_stats[i], 0,
+ sizeof (admin_c.cache_stats[0]));
+ }
+ }
+ (void) memcpy(((char *)outbuf) + phdr->data_off,
+ &admin_c, sizeof (admin_c));
+
+ return (0);
+}
+
+void
+_nscd_client_showstats()
+{
+ (void) printf("nscd configuration:\n\n");
+ (void) printf("%10d server debug level\n", admin_c.debug_level);
+ (void) printf("\"%s\" is server log file\n", admin_c.logfile);
+
+ (void) nsc_info(NULL, NULL, admin_c.cache_cfg, admin_c.cache_stats);
+}
+
+/*ARGSUSED*/
+nscd_rc_t
+_nscd_server_setadmin(nscd_admin_mod_t *set)
+{
+ nscd_rc_t rc = NSCD_ADMIN_FAIL_TO_SET;
+ nscd_cfg_handle_t *h;
+ int i, j;
+ char *group = "param-group-cache";
+ char *dbname;
+ nscd_cfg_error_t *err = NULL;
+ char *me = "_nscd_server_setadmin";
+
+ if (set == NULL)
+ set = &admin_mod;
+
+ /* one setadmin at a time */
+ (void) mutex_lock(&mod_lock);
+
+ _NSCD_LOG_IF(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_DEBUG) {
+
+ _nscd_logit(me, "total_size = %d\n", set->total_size);
+
+ _nscd_logit(me, "debug_level_set = %d, debug_level = %d\n",
+ set->debug_level_set, set->debug_level);
+
+ _nscd_logit(me, "logfile_set = %d, logfile = %s\n",
+ set->logfile_set, *set->logfile == '\0' ?
+ "" : set->logfile);
+
+ _nscd_logit(me, "cache_cfg_num = %d\n",
+ set->cache_cfg_num);
+ _nscd_logit(me, "cache_flush_num = %d\n",
+ set->cache_flush_num);
+ }
+
+ /*
+ * global admin stuff
+ */
+
+ if (set->debug_level_set == nscd_true) {
+ if (_nscd_set_debug_level(set->debug_level)
+ != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to set debug level %d\n",
+ set->debug_level);
+
+ goto err_exit;
+ }
+ admin_c.debug_level = set->debug_level;
+ }
+
+ if (set->logfile_set == nscd_true) {
+ if (_nscd_set_log_file(set->logfile) != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to set log file %s\n", set->logfile);
+
+ goto err_exit;
+ }
+ (void) strlcpy(admin_c.logfile, set->logfile,
+ NSCD_LOGFILE_LEN);
+ }
+
+ /*
+ * For caches to be changed
+ */
+ if (set->cache_cfg_num > CACHE_CTX_COUNT) {
+
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "number of caches (%d) to change out of bound %s\n",
+ set->cache_cfg_num);
+
+ goto err_exit;
+ }
+
+ for (i = 0; i < set->cache_cfg_num; i++) {
+
+ nscd_cfg_cache_t *new_cfg;
+
+ j = set->cache_cfg_set[i];
+ new_cfg = &set->cache_cfg[i];
+ dbname = cache_name[j];
+ if (cache_ctx_p[j] == NULL) {
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to find cache context for %s\n",
+ dbname);
+ }
+
+ rc = _nscd_cfg_get_handle(group, dbname, &h, NULL);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to get handle for < %s : %s >\n",
+ dbname, group);
+
+ goto err_exit;
+ }
+
+ rc = _nscd_cfg_set(h, new_cfg, &err);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to set admin data for < %s : %s >\n",
+ dbname, group);
+
+ _nscd_cfg_free_handle(h);
+
+ goto err_exit;
+ }
+ _nscd_cfg_free_handle(h);
+ }
+
+ /*
+ * For caches to be flushed
+ */
+ if (set->cache_flush_num > CACHE_CTX_COUNT) {
+
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "number of caches (%d) to flush out of bound %s\n",
+ set->cache_flush_num);
+
+ goto err_exit;
+ }
+
+ for (i = 0; i < set->cache_flush_num; i++) {
+ int j;
+
+ j = set->cache_flush_set[i];
+
+ if (cache_ctx_p[j] == NULL) {
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to find cache context for %s\n",
+ dbname);
+ }
+ nsc_invalidate(cache_ctx_p[j], NULL, NULL);
+ }
+
+ rc = NSCD_SUCCESS;
+ err_exit:
+
+ (void) mutex_unlock(&mod_lock);
+ return (rc);
+}
+
+
+/*ARGSUSED*/
+void
+_nscd_door_setadmin(void *buf)
+{
+ nscd_rc_t rc;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_door_setadmin";
+
+ rc = _nscd_server_setadmin(NSCD_N2N_DOOR_DATA(nscd_admin_mod_t, buf));
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_ADMIN, NSCD_LOG_LEVEL_ERROR)
+ (me, "SETADMIN call failed\n");
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, rc);
+ } else {
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+ }
+}
+
+/*
+ * for a database 'dbname', add config value 'val' of option 'opt'
+ * to the global admin_mod structure
+ */
+int
+_nscd_add_admin_mod(char *dbname, char opt,
+ char *val, char *msg, int msglen) {
+ int i, j;
+ nscd_cfg_cache_t *cfg;
+ nscd_cfg_group_info_t gi = NSCD_CFG_GROUP_INFO_CACHE;
+ char dbn[64], *cp;
+
+ /* set initial admin_mod size; assume no cache config to set */
+ if (admin_mod.total_size == 0)
+ admin_mod.total_size = sizeof (admin_mod) -
+ sizeof (admin_mod.cache_cfg);
+
+ /* global admin stuff */
+ if (opt == 'l' || opt == 'd') {
+ if (opt == 'l') {
+ (void) strlcpy(admin_mod.logfile,
+ val, NSCD_LOGFILE_LEN);
+ admin_mod.logfile_set = nscd_true;
+ } else {
+ admin_mod.debug_level = atoi(val);
+ admin_mod.debug_level_set = nscd_true;
+ }
+ return (0);
+ }
+
+ /* options to be processed next requires cache name */
+ (void) strlcpy(dbn, dbname, sizeof (dbn));
+ if ((cp = strchr(dbn, ',')) != NULL)
+ *cp = '\0';
+ i = get_cache_idx(dbn);
+ if (i == -1) {
+ (void) snprintf(msg, msglen,
+ gettext("invalid cache name \"%s\""), dbn);
+ return (-1);
+ }
+
+ /* flush cache ? */
+ if (opt == 'i') {
+ admin_mod.cache_flush_set[admin_mod.cache_flush_num++] = i;
+ return (0);
+ }
+
+ /* options to be processed next requires a param value */
+ if (val == NULL) {
+ (void) snprintf(msg, msglen,
+ gettext("value missing after \"%s\""), dbn);
+ return (-1);
+ }
+
+ /* try to use an existing cache_cfg in admin_mod */
+ for (j = 0; j < admin_mod.cache_cfg_num; j++) {
+ if (admin_mod.cache_cfg_set[j] == i)
+ break;
+ }
+
+ /* no existing one, set up another one */
+ if (j == admin_mod.cache_cfg_num) {
+ admin_mod.cache_cfg_set[j] = i;
+ admin_mod.cache_cfg_num++;
+ admin_mod.total_size += sizeof (admin_mod.cache_cfg[0]);
+ }
+
+ cfg = &admin_mod.cache_cfg[j];
+ cfg->gi.num_param = gi.num_param;
+
+ switch (opt) {
+
+ case 'e':
+ /* enable cache */
+
+ _nscd_cfg_bitmap_set_nth(cfg->gi.bitmap, 0);
+ if (strcmp(val, "yes") == 0)
+ cfg->enable = nscd_true;
+ else if (strcmp(val, "no") == 0)
+ cfg->enable = nscd_false;
+ else {
+ (void) snprintf(msg, msglen,
+ gettext("\"yes\" or \"no\" not specified after \"%s\""), dbn);
+ return (-1);
+ }
+ break;
+
+ case 'c':
+ /* check files */
+
+ _nscd_cfg_bitmap_set_nth(cfg->gi.bitmap, 3);
+ if (strcmp(val, "yes") == 0)
+ cfg->check_files = nscd_true;
+ else if (strcmp(val, "no") == 0)
+ cfg->check_files = nscd_false;
+ else {
+ (void) snprintf(msg, msglen,
+ gettext("\"yes\" or \"no\" not specified after \"%s\""), dbn);
+ return (-1);
+ }
+ break;
+
+ case 'p':
+ /* positive time to live */
+
+ _nscd_cfg_bitmap_set_nth(cfg->gi.bitmap, 5);
+ cfg->pos_ttl = atoi(val);
+ break;
+
+ case 'n':
+ /* negative time to live */
+
+ _nscd_cfg_bitmap_set_nth(cfg->gi.bitmap, 6);
+ cfg->neg_ttl = atoi(val);
+ break;
+
+ case 'h':
+ /* keep hot count */
+
+ _nscd_cfg_bitmap_set_nth(cfg->gi.bitmap, 7);
+ cfg->keephot = atoi(val);
+ break;
+ }
+
+ return (0);
+}
+
+int
+_nscd_client_getadmin(char opt)
+{
+ int callnum;
+ nss_pheader_t phdr;
+
+ if (opt == 'G')
+ callnum = NSCD_GETPUADMIN;
+ else
+ callnum = NSCD_GETADMIN;
+
+ (void) _nscd_doorcall_data(callnum, NULL, sizeof (admin_c),
+ &admin_c, sizeof (admin_c), &phdr);
+
+ if (NSCD_STATUS_IS_NOT_OK(&phdr)) {
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_nscd_client_setadmin()
+{
+ return (_nscd_doorcall_data(NSCD_SETADMIN, &admin_mod,
+ sizeof (admin_mod), NULL, 0, NULL));
+}
diff --git a/usr/src/cmd/nscd/nscd_admin.h b/usr/src/cmd/nscd/nscd_admin.h
new file mode 100644
index 0000000000..520290e420
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_admin.h
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_ADMIN_H
+#define _NSCD_ADMIN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cache.h"
+#include "nscd_common.h"
+#include "nscd_config.h"
+
+#define NSCD_LOGFILE_LEN 128
+
+/*
+ * structure used for door call NSCD_GETADMIN and NSCD_GETPUADMIN
+ */
+typedef struct nscd_admin {
+ int debug_level;
+ char logfile[NSCD_LOGFILE_LEN];
+ nscd_cfg_cache_t cache_cfg[CACHE_CTX_COUNT];
+ nscd_cfg_stat_cache_t cache_stats[CACHE_CTX_COUNT];
+} nscd_admin_t;
+
+/*
+ * structure used for door call NSCD_SETADMIN and NSCD_SETPUADMIN
+ */
+typedef struct nscd_admin_mod {
+ int total_size;
+ nscd_bool_t debug_level_set;
+ nscd_bool_t logfile_set;
+ uint8_t cache_cfg_set[CACHE_CTX_COUNT];
+ uint8_t cache_flush_set[CACHE_CTX_COUNT];
+ nscd_bool_t global_cfg_set;
+ uint8_t cache_cfg_num;
+ uint8_t cache_flush_num;
+ int debug_level;
+ char logfile[NSCD_LOGFILE_LEN];
+ nscd_cfg_cache_t cache_cfg[CACHE_CTX_COUNT];
+} nscd_admin_mod_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+int _nscd_client_getadmin(char opt);
+int _nscd_client_setadmin();
+void _nscd_client_showstats();
+nscd_rc_t _nscd_server_setadmin(nscd_admin_mod_t *set);
+int _nscd_door_getadmin(void *outbuf);
+void _nscd_door_setadmin(void *buf);
+int _nscd_add_admin_mod(char *dbname, char opt,
+ char *val, char *msg, int msglen);
+
+#endif /* _NSCD_ADMIN_H */
diff --git a/usr/src/cmd/nscd/nscd_biggest.c b/usr/src/cmd/nscd/nscd_biggest.c
index 7ddfda863e..a0d6c9edff 100644
--- a/usr/src/cmd/nscd/nscd_biggest.c
+++ b/usr/src/cmd/nscd/nscd_biggest.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,87 +29,54 @@
#include <string.h>
#include <stdlib.h>
-/*
- * routines to find largest n numbers, carrying 4 bytes of data
- */
+#include "cache.h"
-int *
+nsc_keephot_t *
maken(int n)
{
- int * ret;
-
- n++;
+ nsc_keephot_t *ret;
- ret = (int *) memset(malloc(2 * n *sizeof (int)),
- -1, 2 * n * sizeof (int));
- ret[0] = n - 1;
+ ++n;
+ ret = (nsc_keephot_t *)calloc(n, sizeof (nsc_keephot_t));
+ if (ret == NULL)
+ return (NULL);
+ ret[0].num = n - 1;
return (ret);
}
-int
-insertn(int * table, int n, int data)
+void *
+insertn(nsc_keephot_t *table, uint_t n, void *data)
{
- int size = *table;
- int guess, base, last;
- int olddata;
+ void *olddata;
+ int size, guess, base, last;
- if (table[1] > n)
+ if (n < 1 || table[1].num > n) {
return (data);
+ }
- if (table[size] < n) /* biggest so far */
+ size = table[0].num;
+ if (table[size].num < n) /* biggest so far */
guess = size;
else {
base = 1;
last = size;
while (last >= base) {
guess = (last+base)/2;
- if (table[guess] == n)
+ if (table[guess].num == n)
goto doit;
- if (table[guess] > n)
- last = guess -1;
+ if (table[guess].num > n)
+ last = guess - 1;
else
base = guess + 1;
}
guess = last;
}
- doit:
- olddata = table[2 + size];
- memmove(table + 1, table+2, sizeof (int) * (guess-1));
- memmove(table + 2 + size, table + 3 + size, sizeof (int) * (guess-1));
- table[guess + size + 1] = data;
- table[guess] = n;
- return (olddata);
-}
-/*
- * test code
- */
-#if 0
-int
-main(int argc, char * argv[])
-{
- int * t;
- char buffer[100];
- int i, n;
- char * tmp;
-
- t = maken(100);
-
- for (i = 0; i < 1100; i++) {
- n = random();
- sprintf(buffer, "trial %d: %d", i, n);
- tmp = (char *)insertn(t, n, (int)strdup(buffer));
- if (tmp != -1) {
- printf("freeing %s\n", tmp);
- free(tmp);
- }
- }
-
- for (i = 1; i <= 100; i++) {
- printf("%d: %s\n", i, t[100 + 1 + i]);
- free((char *)t[100 + 1 + i]);
- }
-
- free(t);
+doit:
+ olddata = table[1].ptr;
+ (void) memmove(table + 1, table + 2,
+ sizeof (nsc_keephot_t) * (guess-1));
+ table[guess].ptr = data;
+ table[guess].num = n;
+ return (olddata);
}
-#endif
diff --git a/usr/src/cmd/nscd/nscd_cfgdef.h b/usr/src/cmd/nscd/nscd_cfgdef.h
new file mode 100644
index 0000000000..09c9584463
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_cfgdef.h
@@ -0,0 +1,1413 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_CFGDEF_H
+#define _NSCD_CFGDEF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <limits.h>
+#include <nss_dbdefs.h>
+#include "nscd_config.h"
+#include "nscd_log.h"
+#include "cache.h"
+
+/*
+ * structure used for preliminary checking of an integer
+ * configuration value
+ */
+typedef struct {
+ int min;
+ int max;
+} nscd_cfg_int_check_t;
+
+/*
+ * structure used for preliminary checking of a bitmap
+ * configuration value
+ */
+typedef struct {
+ nscd_cfg_bitmap_t valid_bits;
+} nscd_cfg_bitmap_check_t;
+
+/*
+ * structure used for preliminary checking of a string
+ * configuration value
+ */
+typedef struct {
+ nscd_bool_t must_not_null;
+ int maxlen;
+} nscd_cfg_str_check_t;
+
+/*
+ * Per nsswitch database config data
+ */
+typedef struct {
+ nscd_cfg_frontend_t fe;
+ nscd_cfg_switch_t sw;
+ nscd_cfg_cache_t cache;
+} nscd_cfg_nsw_db_data_t;
+
+/*
+ * Per nsswitch database statistics data
+ */
+typedef struct {
+ nscd_cfg_stat_switch_t sw;
+ nscd_cfg_stat_cache_t cache;
+} nscd_cfg_stat_nsw_db_data_t;
+
+/*
+ * global statistics data
+ */
+typedef struct {
+ nscd_cfg_stat_global_log_t log;
+ nscd_cfg_stat_global_switch_t sw;
+ nscd_cfg_stat_cache_t cache;
+} nscd_cfg_stat_global_data_t;
+
+/*
+ * global config data
+ */
+typedef struct {
+ nscd_cfg_global_log_t log;
+ nscd_cfg_global_frontend_t fe;
+ nscd_cfg_global_selfcred_t sc;
+ nscd_cfg_global_switch_t sw;
+ nscd_cfg_global_cache_t cache;
+} nscd_cfg_global_data_t;
+
+/*
+ * structure for handling the switch database specific group
+ * or parameter default
+ */
+typedef struct nscd_cfg_nsw_spc_default {
+ char *db;
+ int group_off;
+ int param_off;
+ void *data; /* pointer or link to data */
+ int data_len;
+} nscd_cfg_nsw_spc_default_t;
+
+/*
+ * name service switch source (repository) table
+ */
+nscd_cfg_id_t _nscd_cfg_nsw_src[] = {
+ { 0, "files" },
+ { 1, "ldap" },
+ { 2, "nis" },
+ { 3, "nisplus" },
+ { 4, "dns" },
+ { 5, "compat" },
+ { 6, "user" },
+ { -1, NULL }
+};
+
+/*
+ * name service related smf service table
+ * (the order of the services should match the order of the source
+ * listed above, 0: files, 1: ldap, 2: nis, 3: nisplus. dns is
+ * not needed)
+ */
+nscd_cfg_id_t _nscd_cfg_smf_services[] = {
+ { 0, "svc:/system/name-service-cache:default"},
+ { 1, "svc:/network/ldap/client:default" },
+ { 2, "svc:/network/nis/client:default" },
+ { 3, "svc:/network/rpc/nisplus:default" },
+ { -1, NULL }
+};
+
+/*
+ * name service database table
+ */
+nscd_cfg_id_t _nscd_cfg_nsw_db[] = {
+ { 0, NSS_DBNAM_PASSWD },
+ { 1, NSS_DBNAM_GROUP },
+ { 2, NSS_DBNAM_HOSTS },
+ { 3, NSS_DBNAM_IPNODES },
+ { 4, NSS_DBNAM_EXECATTR },
+ { 5, NSS_DBNAM_PROFATTR },
+ { 6, NSS_DBNAM_USERATTR },
+ { 7, NSS_DBNAM_NETWORKS },
+ { 8, NSS_DBNAM_PROTOCOLS },
+ { 9, NSS_DBNAM_RPC },
+ { 10, NSS_DBNAM_ETHERS },
+ { 11, NSS_DBNAM_NETMASKS },
+ { 12, NSS_DBNAM_BOOTPARAMS },
+ { 13, NSS_DBNAM_PUBLICKEY },
+ { 14, NSS_DBNAM_NETGROUP },
+ { 15, NSS_DBNAM_SERVICES },
+ { 16, NSS_DBNAM_PRINTERS },
+ { 17, NSS_DBNAM_AUTHATTR },
+ { 18, NSS_DBNAM_PROJECT },
+ { 19, NSS_DBNAM_SHADOW },
+ { 20, NSS_DBNAM_AUDITUSER },
+ { 21, NSS_DBNAM_TSOL_TP },
+ { 22, NSS_DBNAM_TSOL_RH },
+ /* pseudo-databases for the compat backend */
+ { 23, NSS_DBNAM_PASSWD_COMPAT },
+ { 24, NSS_DBNAM_GROUP_COMPAT },
+#define NSS_DBNAM_COMPAT_NUM_DB 5
+ /*
+ * pseudo-databases that use the switch policy that is
+ * configured for NSS_DBNAM_PASSWD_COMPAT
+ */
+ { 25, NSS_DBNAM_PASSWD },
+ { 26, NSS_DBNAM_SHADOW },
+ { 27, NSS_DBNAM_AUDITUSER },
+ { 28, NSS_DBNAM_USERATTR },
+ /*
+ * pseudo-database that uses the switch policy that is
+ * configured for NSS_DBNAM_GROUP_COMPAT
+ */
+ { 29, NSS_DBNAM_GROUP },
+ { -1, NULL }
+};
+
+/*
+ * A special way to indicate all switch databases
+ */
+static nscd_cfg_id_t _nscd_cfg_nsw_alldb = {
+ NSCD_CFG_NSW_ALLDB_INDEX,
+ NSCD_CFG_NSW_ALLDB
+};
+
+/*
+ * data for preliminary checking of the log configuration
+ */
+static nscd_cfg_str_check_t NSCD_CFG_LOGFILE_PCHECK =
+ {nscd_false, PATH_MAX};
+static nscd_cfg_bitmap_check_t NSCD_CFG_LOGCOMP_PCHECK =
+ {NSCD_LOG_ALL};
+static nscd_cfg_bitmap_check_t NSCD_CFG_LOGLEVEL_PCHECK =
+ {NSCD_LOG_LEVEL_ALL};
+
+/* data for preliminary checking of the switch configuration */
+static nscd_cfg_str_check_t NSCD_CFG_NSWCFGSTR_PCHECK =
+ {nscd_true, 128};
+
+/*
+ * macros for defining the static param table
+ */
+#define NSCD_CFG_PGROUP_DESC(pn, type, pflag, gf, g_in_t, pcheck_p,\
+ nfunc_name, vfunc_name) \
+ { \
+ {-1, pn}, type, (NSCD_CFG_PFLAG_GROUP | pflag), \
+ 0, 0, 0,\
+ NSCD_SIZEOF(g_in_t, gf), offsetof(g_in_t, gf), -1, \
+ pcheck_p, nfunc_name, vfunc_name, NULL, NULL \
+ }
+
+#define NSCD_CFG_PARAM_DESC(pn, type, pflag, pf, p_in_t, \
+ gf, g_in_t, pcheck_p, nfunc_name, vfunc_name) \
+ { \
+ {-1, pn}, type, pflag, \
+ NSCD_SIZEOF(p_in_t, pf), offsetof(p_in_t, pf), -1, \
+ NSCD_SIZEOF(g_in_t, gf), offsetof(g_in_t, gf), -1, \
+ pcheck_p, nfunc_name, vfunc_name, NULL, NULL \
+ }
+
+#define NSCD_CFG_PGROUP_DESC_NULL \
+ { \
+ {-1, NULL}, -1, NSCD_CFG_PFLAG_GROUP, \
+ 0, 0, 0, \
+ 0, 0, 0, \
+ NULL, NULL, NULL, NULL, NULL \
+ }
+#define NSCD_CFG_FUNC_NAME_AS_GROUP "(as_group)"
+
+/*
+ * the static config parameter description table
+ */
+static nscd_cfg_param_desc_t _nscd_cfg_param_desc[] = {
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-global-log",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_GLOBAL,
+ log,
+ nscd_cfg_global_data_t,
+ NULL,
+ "_nscd_cfg_log_notify",
+ "_nscd_cfg_log_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "logfile",
+ NSCD_CFG_DATA_STRING,
+ NSCD_CFG_PFLAG_GLOBAL |
+ NSCD_CFG_PFLAG_VLEN_DATA,
+ logfile,
+ nscd_cfg_global_log_t,
+ log,
+ nscd_cfg_global_data_t,
+ &NSCD_CFG_LOGFILE_PCHECK,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "debug-level",
+ NSCD_CFG_DATA_BITMAP,
+ NSCD_CFG_PFLAG_GLOBAL,
+ debug_level,
+ nscd_cfg_global_log_t,
+ log,
+ nscd_cfg_global_data_t,
+ &NSCD_CFG_LOGLEVEL_PCHECK,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "debug-components",
+ NSCD_CFG_DATA_BITMAP,
+ NSCD_CFG_PFLAG_GLOBAL,
+ debug_comp,
+ nscd_cfg_global_log_t,
+ log,
+ nscd_cfg_global_data_t,
+ &NSCD_CFG_LOGCOMP_PCHECK,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-global-frontend",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_GLOBAL,
+ fe,
+ nscd_cfg_global_data_t,
+ NULL,
+ "_nscd_cfg_frontend_notify",
+ "_nscd_cfg_frontend_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "common-worker-threads",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_SEND_BIT_SELECTED |
+ NSCD_CFG_PFLAG_GLOBAL,
+ common_worker_threads,
+ nscd_cfg_global_frontend_t,
+ fe,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "cache-hit-threads",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_SEND_BIT_SELECTED |
+ NSCD_CFG_PFLAG_GLOBAL,
+ cache_hit_threads,
+ nscd_cfg_global_frontend_t,
+ fe,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-global-selfcred",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_GLOBAL,
+ sc,
+ nscd_cfg_global_data_t,
+ NULL,
+ "_nscd_cfg_selfcred_notify",
+ "_nscd_cfg_selfcred_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "enable-selfcred",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_GLOBAL,
+ enable_selfcred,
+ nscd_cfg_global_selfcred_t,
+ sc,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "max-per-user-nscd",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_GLOBAL,
+ max_per_user_nscd,
+ nscd_cfg_global_selfcred_t,
+ sc,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "per-user-nscd-ttl",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_GLOBAL,
+ per_user_nscd_ttl,
+ nscd_cfg_global_selfcred_t,
+ sc,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-global-switch",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_GLOBAL,
+ sw,
+ nscd_cfg_global_data_t,
+ NULL,
+ "_nscd_cfg_switch_notify",
+ "_nscd_cfg_switch_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "global-enable-lookup",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_GLOBAL,
+ enable_lookup_g,
+ nscd_cfg_global_switch_t,
+ sw,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "global-enable-loopback-checking",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_GLOBAL,
+ enable_loopback_checking_g,
+ nscd_cfg_global_switch_t,
+ sw,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "global-check-smf-state-interval",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_GLOBAL,
+ check_smf_state_interval_g,
+ nscd_cfg_global_switch_t,
+ sw,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-global-cache",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_INIT_SET_ALL_DB |
+ NSCD_CFG_PFLAG_GLOBAL,
+ cache,
+ nscd_cfg_global_data_t,
+ NULL,
+ "_nscd_cfg_cache_notify",
+ "_nscd_cfg_cache_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "global-enable-cache",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_GLOBAL,
+ enable,
+ nscd_cfg_global_cache_t,
+ cache,
+ nscd_cfg_global_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ /* non-global config param from this point on */
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-frontend",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP,
+ fe,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ "_nscd_cfg_frontend_notify",
+ "_nscd_cfg_frontend_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "worker-thread-per-nsw-db",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ worker_thread_per_nsw_db,
+ nscd_cfg_frontend_t,
+ fe,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-switch",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP |
+ NSCD_CFG_PFLAG_NONE,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ "_nscd_cfg_switch_notify",
+ "_nscd_cfg_switch_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "nsw-config-string",
+ NSCD_CFG_DATA_STRING,
+ NSCD_CFG_PFLAG_VLEN_DATA |
+ NSCD_CFG_PFLAG_LINKED,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ &NSCD_CFG_NSWCFGSTR_PCHECK,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "nsw-config-database",
+ NSCD_CFG_DATA_STRING,
+ NSCD_CFG_PFLAG_VLEN_DATA |
+ NSCD_CFG_PFLAG_HIDDEN,
+ nsw_config_db,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ &NSCD_CFG_NSWCFGSTR_PCHECK,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "enable-lookup",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ enable_lookup,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "enable-loopback-checking",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ enable_loopback_checking,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "max-nsw-state-per-db",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ max_nsw_state_per_db,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "max-nsw-state-per-thread",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ max_nsw_state_per_thread,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "max-getent-ctx-per-db",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ max_getent_ctx_per_db,
+ nscd_cfg_switch_t,
+ sw,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC(
+ "param-group-cache",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ "_nscd_cfg_cache_notify",
+ "_nscd_cfg_cache_verify"),
+
+ NSCD_CFG_PARAM_DESC(
+ "enable-cache",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ enable,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "enable-per-user-cache",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ per_user,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "avoid-nameservice",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ avoid_ns,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "check-files",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_NONE,
+ check_files,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "check-file-interval",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ check_interval,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "positive-time-to-live",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ pos_ttl,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "negative-time-to-live",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ neg_ttl,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "keep-hot-count",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ keephot,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "hint-size",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ hint_size,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "maximum-entries-allowed",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_NONE,
+ maxentries,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "suggested-size",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_PFLAG_OBSOLETE,
+ suggestedsize,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PARAM_DESC(
+ "old-data-ok",
+ NSCD_CFG_DATA_BOOLEAN,
+ NSCD_CFG_PFLAG_OBSOLETE,
+ old_data_ok,
+ nscd_cfg_cache_t,
+ cache,
+ nscd_cfg_nsw_db_data_t,
+ NULL,
+ NSCD_CFG_FUNC_NAME_AS_GROUP,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_PGROUP_DESC_NULL
+};
+
+/*
+ * defaults for the global configuration
+ */
+static nscd_cfg_global_data_t nscd_cfg_global_default = {
+
+ /*
+ * nscd_cfg_global_log_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_GLOBAL_LOG,
+ NULL,
+ NSCD_LOG_LEVEL_ERROR, /* debug_level */
+ NSCD_LOG_CACHE, /* debug_comp */
+
+ },
+
+ /*
+ * nscd_cfg_global_frontend_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_GLOBAL_FRONTEND,
+ 20, /* common_worker_threads */
+ 20, /* cache_hit_threads */
+
+ },
+
+ /*
+ * nscd_cfg_global_selfcred_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_GLOBAL_SELFCRED,
+ nscd_true, /* enable_selfcred */
+ 1000, /* max_per_user_nscd */
+ 120, /* per_user_nscd_ttl: 120 seconds */
+
+ },
+
+ /*
+ * nscd_cfg_global_switch_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_GLOBAL_SWITCH,
+ nscd_true, /* enable_lookup_g */
+ nscd_false, /* enable_loopback_checking_g */
+ 120, /* check_smf_state_interval_g */
+
+ },
+
+ /*
+ * nscd_cfg_global_cache_t
+ */
+ NSCD_CFG_GLOBAL_CACHE_DEFAULTS
+};
+
+/*
+ * defaults for the per switch database configuration
+ */
+static nscd_cfg_nsw_db_data_t nscd_cfg_nsw_db_data_default = {
+
+ /*
+ * nscd_cfg_frontend_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_FRONTEND,
+ 10, /* worker_thread_per_nsw_db */
+
+ },
+
+ /*
+ * nscd_cfg_switch_t
+ */
+ {
+
+ NSCD_CFG_GROUP_INFO_SWITCH,
+ "nis files", /* nsw_config_string */
+ NULL, /* nsw_config_db */
+ nscd_true, /* enable_lookup */
+ nscd_false, /* enable_loopback_checking */
+ 10, /* max_nsw_state_per_db */
+ 5, /* max_nsw_state_per_thread */
+ 10, /* max_getent_ctx_per_db */
+
+ },
+
+ /*
+ * nscd_cfg_cache_t
+ */
+ NSCD_CFG_CACHE_DEFAULTS
+};
+
+/*
+ * macros for defining the database specific defaults
+ */
+#define NSCD_CFG_DB_DEFAULT_PARAM(db, gf, pf, gt, defaddr, deflen) \
+ { \
+ db, offsetof(nscd_cfg_nsw_db_data_t, gf), \
+ offsetof(gt, pf), defaddr, deflen \
+ }
+
+#define NSCD_CFG_DB_DEFAULT_GROUP(db, gf, defaddr, deflen) \
+ { \
+ db, offsetof(nscd_cfg_nsw_db_data_t, gf), \
+ 0, defaddr, deflen \
+ }
+
+#define NSCD_CFG_DB_DEFAULT_NULL \
+ { \
+ NULL, 0, 0, NULL, 0 \
+ }
+
+/*
+ * shadow, user_attr, and audit_user use the same switch policy
+ * as that of passwd. exec_attr use that of prof_attr.
+ */
+static char *nscd_cfg_shadow_cfg_db = NSS_DBNAM_PASSWD;
+static char *nscd_cfg_userattr_cfg_db = NSS_DBNAM_PASSWD;
+static char *nscd_cfg_auuser_cfg_db = NSS_DBNAM_PASSWD;
+static char *nscd_cfg_execattr_cfg_db = NSS_DBNAM_PROFATTR;
+
+/*
+ * default switch policy for pseudo-databases passwd_compat and
+ * and group_compa is "nis"
+ */
+static char *nscd_cfg_def_passwd_compat = NSS_DEFCONF_PASSWD_COMPAT;
+static char *nscd_cfg_def_group_compat = NSS_DEFCONF_GROUP_COMPAT;
+
+static nscd_cfg_nsw_spc_default_t nscd_cfg_passwd_cfg_link =
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_PASSWD,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ NULL,
+ NSCD_SIZEOF(nscd_cfg_switch_t, nsw_config_string));
+
+static nscd_cfg_nsw_spc_default_t nscd_cfg_profattr_cfg_link =
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_PROFATTR,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ NULL,
+ NSCD_SIZEOF(nscd_cfg_switch_t, nsw_config_string));
+
+
+/*
+ * switch database specific defaults
+ */
+nscd_cfg_nsw_spc_default_t _nscd_cfg_nsw_spc_default[] = {
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_SHADOW,
+ sw,
+ nsw_config_db,
+ nscd_cfg_switch_t,
+ &nscd_cfg_shadow_cfg_db,
+ sizeof (nscd_cfg_shadow_cfg_db)),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_USERATTR,
+ sw,
+ nsw_config_db,
+ nscd_cfg_switch_t,
+ &nscd_cfg_userattr_cfg_db,
+ sizeof (nscd_cfg_userattr_cfg_db)),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_AUDITUSER,
+ sw,
+ nsw_config_db,
+ nscd_cfg_switch_t,
+ &nscd_cfg_auuser_cfg_db,
+ sizeof (nscd_cfg_auuser_cfg_db)),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_EXECATTR,
+ sw,
+ nsw_config_db,
+ nscd_cfg_switch_t,
+ &nscd_cfg_execattr_cfg_db,
+ sizeof (nscd_cfg_execattr_cfg_db)),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_PASSWD_COMPAT,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_def_passwd_compat,
+ sizeof (nscd_cfg_def_passwd_compat)),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_GROUP_COMPAT,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_def_group_compat,
+ sizeof (nscd_cfg_def_group_compat)),
+
+ NSCD_CFG_DB_DEFAULT_NULL
+};
+
+/*
+ * switch database specific defaults that are linked to
+ * those of other databases
+ */
+nscd_cfg_nsw_spc_default_t _nscd_cfg_nsw_link_default[] = {
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_SHADOW,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_passwd_cfg_link,
+ 0),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_USERATTR,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_passwd_cfg_link,
+ 0),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_AUDITUSER,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_passwd_cfg_link,
+ 0),
+
+ NSCD_CFG_DB_DEFAULT_PARAM(
+ NSS_DBNAM_EXECATTR,
+ sw,
+ nsw_config_string,
+ nscd_cfg_switch_t,
+ &nscd_cfg_profattr_cfg_link,
+ 0),
+
+ NSCD_CFG_DB_DEFAULT_NULL
+};
+
+/*
+ * macros for defining the static stats table
+ */
+#define NSCD_CFG_SGROUP_DESC(sn, type, sflag, gi, \
+ gf, g_in_t, gsfunc_name) \
+ { \
+ {-1, sn}, type, NSCD_CFG_SFLAG_GROUP | sflag, gi, \
+ 0, 0, 0,\
+ NSCD_SIZEOF(g_in_t, gf), offsetof(g_in_t, gf), -1, \
+ gsfunc_name, NULL \
+ }
+
+#define NSCD_CFG_STAT_DESC(sn, type, sflag, sf, s_in_t, \
+ gf, g_in_t, gsfunc_name) \
+ { \
+ {-1, sn}, type, sflag, NSCD_CFG_GROUP_INFO_NULL, \
+ NSCD_SIZEOF(s_in_t, sf), offsetof(s_in_t, sf), -1, \
+ NSCD_SIZEOF(g_in_t, gf), offsetof(g_in_t, gf), -1, \
+ gsfunc_name, NULL \
+ }
+
+#define NSCD_CFG_SGROUP_DESC_NULL \
+ { \
+ {-1, NULL}, -1, NSCD_CFG_SFLAG_GROUP, NULL, \
+ 0, 0, 0, \
+ 0, 0, 0, \
+ NULL, NULL \
+ }
+
+/*
+ * the static statistics description table
+ */
+static nscd_cfg_stat_desc_t _nscd_cfg_stat_desc[] = {
+
+ NSCD_CFG_SGROUP_DESC(
+ "stat-group-global-log",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_SFLAG_GLOBAL,
+ NSCD_CFG_STAT_GROUP_INFO_GLOBAL_LOG,
+ log,
+ nscd_cfg_stat_global_data_t,
+ "_nscd_cfg_log_get_stat"),
+
+ NSCD_CFG_STAT_DESC(
+ "entries-logged",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ entries_logged,
+ nscd_cfg_stat_global_log_t,
+ log,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_SGROUP_DESC(
+ "stat-group-global-switch",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_SFLAG_GLOBAL,
+ NSCD_CFG_STAT_GROUP_INFO_GLOBAL_SWITCH,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ "_nscd_cfg_switch_get_stat"),
+
+ NSCD_CFG_STAT_DESC(
+ "global-lookup-request-received",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ lookup_request_received_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-lookup-request-queued",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ lookup_request_queued_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-lookup-request-in-progress",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ lookup_request_in_progress_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-lookup-request-succeeded",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ lookup_request_succeeded_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-lookup-request-failed",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ lookup_request_failed_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-loopback-nsw-db-skipped",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ loopback_nsw_db_skipped_g,
+ nscd_cfg_stat_global_switch_t,
+ sw,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_SGROUP_DESC(
+ "stat-group-global-cache",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_SFLAG_GLOBAL,
+ NSCD_CFG_STAT_GROUP_INFO_CACHE,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ "_nscd_cfg_cache_get_stat"),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-hits-on-positive",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ pos_hits,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-hits-on-negative",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ neg_hits,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-misses-on-positive",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ pos_misses,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-misses-on-negative",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ neg_misses,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-queries-queued",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ wait_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-total-cache-entries",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ entries,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-complete-cache-invalidations",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ invalidate_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-queries-dropped",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_GLOBAL,
+ drop_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "global-cache-hit-rate",
+ NSCD_CFG_DATA_PERCENT,
+ NSCD_CFG_SFLAG_GLOBAL,
+ hitrate,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_global_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ /* non-global stat from this point on */
+
+ NSCD_CFG_SGROUP_DESC(
+ "stat-group-switch",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_SFLAG_GROUP,
+ NSCD_CFG_STAT_GROUP_INFO_SWITCH,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ "_nscd_cfg_switch_get_stat"),
+
+ NSCD_CFG_STAT_DESC(
+ "lookup-request-received",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ lookup_request_received,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "lookup-request-queued",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ lookup_request_queued,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "lookup-request-in-progress",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ lookup_request_in_progress,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "lookup-request-succeeded",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ lookup_request_succeeded,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "lookup-request-failed",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ lookup_request_failed,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "loopback-nsw-db-skipped",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ loopback_nsw_db_skipped,
+ nscd_cfg_stat_switch_t,
+ sw,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_SGROUP_DESC(
+ "stat-group-cache",
+ NSCD_CFG_DATA_NONE,
+ NSCD_CFG_SFLAG_GROUP,
+ NSCD_CFG_STAT_GROUP_INFO_CACHE,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ "_nscd_cfg_cache_get_stat"),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-hits-on-positive",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ pos_hits,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-hits-on-negative",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ neg_hits,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-misses-on-positive",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ pos_misses,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-misses-on-negative",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ neg_misses,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-queries-queued",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ wait_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "total-cache-entries",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ entries,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "complete-cache-invalidations",
+ NSCD_CFG_DATA_INTEGER,
+ NSCD_CFG_SFLAG_NONE,
+ invalidate_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-hit-rate",
+ NSCD_CFG_DATA_PERCENT,
+ NSCD_CFG_SFLAG_NONE,
+ hitrate,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+ NSCD_CFG_STAT_DESC(
+ "cache-queries-dropped",
+ NSCD_CFG_DATA_PERCENT,
+ NSCD_CFG_SFLAG_NONE,
+ drop_count,
+ nscd_cfg_stat_cache_t,
+ cache,
+ nscd_cfg_stat_nsw_db_data_t,
+ NSCD_CFG_FUNC_NAME_AS_GROUP),
+
+
+ NSCD_CFG_SGROUP_DESC_NULL
+};
+
+/* number of entries in the static tables */
+
+int _nscd_cfg_num_nsw_src =
+ (sizeof (_nscd_cfg_nsw_src) /
+ sizeof (_nscd_cfg_nsw_src[0]) - 1);
+
+int _nscd_cfg_num_smf_services =
+ (sizeof (_nscd_cfg_smf_services) /
+ sizeof (_nscd_cfg_smf_services[0]) - 1);
+
+/* number of supported nsw databases (including pseudo ones) */
+int _nscd_cfg_num_nsw_db_all =
+ (sizeof (_nscd_cfg_nsw_db) /
+ sizeof (_nscd_cfg_nsw_db[0]) - 1);
+
+/* number of supported nsw databases (not including pseudo ones) */
+int _nscd_cfg_num_nsw_db =
+ (sizeof (_nscd_cfg_nsw_db) /
+ sizeof (_nscd_cfg_nsw_db[0]) - 1) -
+ NSS_DBNAM_COMPAT_NUM_DB;
+
+static int _nscd_cfg_num_param =
+ (sizeof (_nscd_cfg_param_desc) /
+ sizeof (_nscd_cfg_param_desc[0]) - 1);
+
+static int _nscd_cfg_num_stat =
+ (sizeof (_nscd_cfg_stat_desc) /
+ sizeof (_nscd_cfg_stat_desc[0]) - 1);
+
+int _nscd_cfg_num_nsw_default =
+ (sizeof (_nscd_cfg_nsw_spc_default) /
+ sizeof (_nscd_cfg_nsw_spc_default[0]) - 1);
+
+int _nscd_cfg_num_link_default =
+ (sizeof (_nscd_cfg_nsw_link_default) /
+ sizeof (_nscd_cfg_nsw_link_default[0]) - 1);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_CFGDEF_H */
diff --git a/usr/src/cmd/nscd/nscd_cfgfile.c b/usr/src/cmd/nscd/nscd_cfgfile.c
new file mode 100644
index 0000000000..f3075ac792
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_cfgfile.c
@@ -0,0 +1,386 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * routine to read configuration file
+ *
+ */
+#include "nscd_config.h"
+#include "nscd_log.h"
+#include <locale.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+static int
+strbreak(char *field[], int array_size, char *s, char *sep)
+{
+ int i;
+ char *lasts, *qp;
+ int inquote;
+
+ qp = strchr(s, '"');
+ for (i = 0; i < array_size && (field[i] =
+ strtok_r((i?(char *)NULL:s), sep, &lasts)); i++);
+
+ if (qp == NULL)
+ return (i);
+
+ inquote = 1;
+ while (++qp < lasts) {
+
+ switch (*qp) {
+
+ case '"':
+ inquote = (inquote == 0);
+ break;
+
+ case '\\':
+ /* escape " */
+ if (inquote == 1 && *(qp + 1) == '"')
+ qp++;
+ break;
+
+ case '\0':
+ if (inquote == 1) {
+ *qp = ' ';
+ i--;
+ }
+
+ break;
+ }
+ }
+
+ return (i);
+}
+
+
+nscd_rc_t
+_nscd_cfg_read_file(
+ char *filename,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_read_file";
+ FILE *in;
+ char buffer[255];
+ char *fields [128];
+ int linecnt;
+ int fieldcnt;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_handle_t *h = NULL;
+ nscd_cfg_param_desc_t *pdesc;
+ char *dbname, *str;
+ void *data_p;
+ int i;
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+
+ union {
+ int i;
+ char data[256];
+ } u;
+
+ if ((in = fopen(filename, "r")) == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("open of configuration file \"%s\" failed: %s"),
+ filename, strerror(errno));
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_FILE_OPEN_ERROR, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ return (NSCD_CFG_FILE_OPEN_ERROR);
+ }
+
+ linecnt = 0;
+ msg[0] = '\0';
+ while (fgets(buffer, sizeof (buffer), in) != NULL) {
+
+ linecnt++;
+ if ((fieldcnt = strbreak(fields, 128, buffer, " \t\n")) ==
+ 0 || *fields[0] == '#') {
+ /* skip blank or comment lines */
+ continue;
+ }
+
+ switch (fieldcnt) {
+
+ case 2:
+ dbname = NULL;
+ str = fields[1];
+ break;
+
+ case 3:
+ dbname = fields[1];
+ str = fields[2];
+ break;
+
+ default:
+
+ (void) strlcpy(u.data, fields[0], sizeof (u.data));
+ for (i = 1; i < fieldcnt; i++) {
+ (void) strlcat(u.data, " ",
+ sizeof (u.data));
+ (void) strlcat(u.data, fields[i],
+ sizeof (u.data));
+ }
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("Syntax error: line %d of configuration "
+ "file: %s : \"%s\""), linecnt, filename, u.data);
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_SYNTAX_ERROR, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ rc = NSCD_CFG_SYNTAX_ERROR;
+ break;
+ }
+
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ rc = _nscd_cfg_get_handle(fields[0], dbname, &h, errorp);
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ pdesc = _nscd_cfg_get_desc(h);
+
+ /* convert string to data */
+ rc = _nscd_cfg_str_to_data(pdesc, str, &u.data,
+ &data_p, errorp);
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ /* do preliminary check based on data type */
+ rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp);
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ rc = _nscd_cfg_set_linked(h, data_p, errorp);
+ _nscd_cfg_free_handle(h);
+ h = NULL;
+ if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS)
+ break;
+ else {
+ _nscd_cfg_free_error(*errorp);
+ *errorp = NULL;
+ }
+ }
+ /* NSCD_CFG_READ_ONLY is not fatal */
+ if (rc == NSCD_CFG_READ_ONLY)
+ rc = NSCD_SUCCESS;
+
+ if (h != NULL)
+ _nscd_cfg_free_handle(h);
+
+ (void) fclose(in);
+
+ if (msg[0] == '\0' && rc != NSCD_SUCCESS) {
+ if (errorp != NULL)
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", NSCD_ERR2MSG(*errorp));
+ }
+
+ return (rc);
+}
+
+nscd_rc_t
+_nscd_cfg_read_nsswitch_file(
+ char *filename,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_read_nsswitch_file";
+ char *pname = "nsw-config-string";
+ FILE *in;
+ char buffer[255];
+ char *cc, *ce, *ce1, *c1, *c2;
+ char *db, *dbe;
+ char *nsscfg;
+ int syntax_err;
+ int linecnt;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_handle_t *h = NULL;
+ nscd_cfg_param_desc_t *pdesc;
+ void *data_p;
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+
+ union {
+ int i;
+ char data[256];
+ } u;
+
+ if ((in = fopen(filename, "r")) == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("open of configuration file \"%s\" failed: %s"),
+ filename, strerror(errno));
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_FILE_OPEN_ERROR, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ return (NSCD_CFG_FILE_OPEN_ERROR);
+ }
+
+ linecnt = 0;
+ msg[0] = '\0';
+ while (fgets(buffer, sizeof (buffer), in) != NULL) {
+
+ linecnt++;
+ syntax_err = 0;
+ /* skip blank or comment lines */
+ if (buffer[0] == '#' || buffer[0] == '\n')
+ continue;
+ /* skip end of line comment */
+ if ((ce = strchr(buffer, '\n')) != NULL)
+ *ce = '\0';
+ else
+ ce = &buffer[255];
+ if ((ce1 = strchr(buffer, '#')) != NULL) {
+ ce = ce1;
+ *ce = '\0';
+ }
+ if ((cc = strchr(buffer, ':')) == NULL) {
+ c1 = buffer;
+ while (isalpha(*c1) && c1 < ce)
+ c1++;
+ if (c1 > ce)
+ syntax_err = 1;
+ else /* blank line */
+ continue;
+ } else {
+ /*
+ * data name goes before ':',
+ * skip spaces on both ends
+ */
+ c2 = cc - 1;
+ while (buffer <= c2 && isspace(*c2))
+ c2--;
+ c1 = buffer;
+ while (c1 <= cc && isspace(*c1))
+ c1++;
+ if (c1 > c2)
+ syntax_err = 1;
+ else {
+ db = c1;
+ dbe = c2 + 1;
+
+ /*
+ * nss config goes after ':',
+ * skip spaces on both ends
+ */
+ c1 = cc + 1;
+ while (c1 <= ce && isspace(*c1))
+ c1++;
+ c2 = ce - 1;
+ while (cc <= c2 && isspace(*c2))
+ c2--;
+ if (c1 > c2)
+ syntax_err = 1;
+ else {
+ *dbe = '\0';
+ nsscfg = c1;
+ *(c2 + 1) = '\0';
+ }
+ }
+ }
+
+ if (syntax_err == 1) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("Syntax error: line %d of configuration "
+ "file: %s : \"%s\""), linecnt, filename, buffer);
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_SYNTAX_ERROR, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ rc = NSCD_CFG_SYNTAX_ERROR;
+ return (rc);
+ }
+
+ rc = _nscd_cfg_get_handle(pname, db, &h, errorp);
+ if (rc != NSCD_SUCCESS) {
+ /* ignore unsupported switch database */
+ if (rc == NSCD_CFG_UNSUPPORTED_SWITCH_DB) {
+ _nscd_cfg_free_error(*errorp);
+ *errorp = NULL;
+ rc = NSCD_SUCCESS;
+ continue;
+ }
+ break;
+ }
+
+ pdesc = _nscd_cfg_get_desc(h);
+
+ /* convert string to data */
+ rc = _nscd_cfg_str_to_data(pdesc, nsscfg, &u.data,
+ &data_p, errorp);
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ /* do preliminary check based on data type */
+ rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp);
+ if (rc != NSCD_SUCCESS)
+ break;
+
+ rc = _nscd_cfg_set_linked(h, data_p, errorp);
+ _nscd_cfg_free_handle(h);
+ h = NULL;
+ if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS)
+ break;
+ else {
+ _nscd_cfg_free_error(*errorp);
+ *errorp = NULL;
+ }
+ }
+ /* NSCD_CFG_READ_ONLY is not fatal */
+ if (rc == NSCD_CFG_READ_ONLY)
+ rc = NSCD_SUCCESS;
+
+ if (h != NULL)
+ _nscd_cfg_free_handle(h);
+
+ (void) fclose(in);
+
+ if (msg[0] == '\0' && rc != NSCD_SUCCESS) {
+ if (errorp != NULL)
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", NSCD_ERR2MSG(*errorp));
+ }
+
+ return (rc);
+}
diff --git a/usr/src/cmd/nscd/nscd_common.h b/usr/src/cmd/nscd/nscd_common.h
new file mode 100644
index 0000000000..7b2ccffd91
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_common.h
@@ -0,0 +1,105 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_COMMON_H
+#define _NSCD_COMMON_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <synch.h>
+
+/*
+ * nscd internal return/error codes
+ */
+typedef enum {
+ NSCD_SUCCESS = 0,
+ NSCD_INITIALIZATION_FAILED,
+ NSCD_CTX_NOT_FOUND,
+ NSCD_DB_ENTRY_FOUND,
+ NSCD_DB_ENTRY_NOT_FOUND,
+ NSCD_INVALID_ARGUMENT,
+ NSCD_NO_MEMORY,
+ NSCD_THREAD_CREATE_ERROR,
+ NSCD_SMF_ERROR,
+ NSCD_CFG_UNSUPPORTED_SWITCH_DB,
+ NSCD_CFG_UNSUPPORTED_SWITCH_SRC,
+ NSCD_CFG_DLOPEN_ERROR,
+ NSCD_CFG_DLSYM_ERROR,
+ NSCD_CFG_SET_PARAM_FAILED,
+ NSCD_CFG_PARAM_DESC_ERROR,
+ NSCD_CFG_STAT_DESC_ERROR,
+ NSCD_CFG_INVALID_HANDLE,
+ NSCD_CFG_PARSE_ERROR,
+ NSCD_CFG_FILE_OPEN_ERROR,
+ NSCD_CFG_FILE_ACCESS_ERROR,
+ NSCD_CFG_SYNTAX_ERROR,
+ NSCD_CFG_PRELIM_CHECK_FAILED,
+ NSCD_CFG_DATA_CONVERSION_FAILED,
+ NSCD_CFG_WRITE_ERROR,
+ NSCD_CFG_READ_ONLY,
+ NSCD_CFG_CHANGE_NOT_ALLOWED,
+ NSCD_CREATE_NSW_STATE_FAILED,
+ NSCD_CREATE_GETENT_CTX_FAILED,
+ NSCD_NSS_BACKEND_NOT_FOUND,
+ NSCD_DOOR_UCRED_ERROR,
+ NSCD_SELF_CRED_NOT_CONFIGURED,
+ NSCD_SELF_CRED_NO_FORKER,
+ NSCD_SELF_CRED_WRONG_NSCD,
+ NSCD_SELF_CRED_MAIN_IMPOSTER,
+ NSCD_SELF_CRED_FORKER_IMPOSTER,
+ NSCD_SELF_CRED_CHILD_IMPOSTER,
+ NSCD_SELF_CRED_NO_DOOR,
+ NSCD_SELF_CRED_NO_CHILD_SLOT,
+ NSCD_SELF_CRED_INVALID_SLOT_NUMBER,
+ NSCD_SELF_CRED_INVALID_SLOT_STATE,
+ NSCD_ADMIN_FAIL_TO_SET,
+ NSCD_CACHE_INVALID_CACHE_NAME,
+ NSCD_CACHE_NO_CACHE_CTX,
+ NSCD_CACHE_DISABLED,
+ NSCD_CACHE_NO_CACHE_FOUND,
+ NSCD_CACHE_AVOID_NS
+
+} nscd_rc_t;
+
+
+/* nscd data type: boolean */
+typedef uint8_t nscd_bool_t;
+#define nscd_true 1
+#define nscd_false 0
+
+/* common functions */
+nscd_rc_t _nscd_init(char *cfgfile);
+nscd_rc_t _nscd_refresh();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_COMMON_H */
diff --git a/usr/src/cmd/nscd/nscd_config.c b/usr/src/cmd/nscd/nscd_config.c
new file mode 100644
index 0000000000..02e3375ab0
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_config.c
@@ -0,0 +1,2923 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h> /* gettext */
+#include <dlfcn.h>
+#include <string.h>
+#include <sys/varargs.h>
+#include <errno.h>
+#include "nscd_db.h"
+#include "nscd_config.h"
+#include "nscd_cfgdef.h"
+#include "nscd_log.h"
+
+typedef struct {
+ rwlock_t *global;
+ rwlock_t *alldb;
+ rwlock_t *nswdb;
+} nscd_cfg_lock_t;
+
+static rwlock_t cfg_paramDB_rwlock = DEFAULTRWLOCK;
+static nscd_db_t *cfg_paramDB = NULL;
+
+static nscd_cfg_global_data_t *nscd_cfg_global_current;
+static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_db_data_current;
+static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_alldb_current;
+static rwlock_t *nscd_cfg_global_rwlock;
+static rwlock_t *nscd_cfg_nsw_db_data_rwlock;
+static rwlock_t *nscd_cfg_nsw_alldb_rwlock;
+
+extern int _nscd_cfg_num_nsw_src_all;
+extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
+
+nscd_cfg_error_t *
+_nscd_cfg_make_error(
+ nscd_rc_t rc,
+ char *msg)
+{
+
+ nscd_cfg_error_t *ret;
+ int size, msglen;
+
+ msglen = (msg != NULL ? strlen(msg) + 1 : 0);
+
+ size = sizeof (nscd_cfg_error_t) + msglen;
+
+ ret = calloc(1, size);
+ if (ret == NULL)
+ return (NULL);
+
+ ret->rc = rc;
+ if (msg != NULL) {
+ ret->msg = (char *)ret +
+ sizeof (nscd_cfg_error_t);
+ (void) memcpy(ret->msg, msg, msglen);
+ }
+
+ return (ret);
+}
+
+static nscd_rc_t
+_nscd_cfg_get_list(
+ nscd_cfg_list_t **list,
+ nscd_cfg_list_type_t type)
+{
+ char *me = "_nscd_cfg_get_list";
+ int i, num, size;
+ nscd_cfg_id_t *l;
+ nscd_cfg_list_t *ret;
+ nscd_cfg_param_desc_t *pl;
+ nscd_cfg_stat_desc_t *sl;
+ void *p;
+
+ if (list == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "invalid argument: list = %p\n", list);
+
+ return (NSCD_INVALID_ARGUMENT);
+ }
+ *list = NULL;
+
+ switch (type) {
+ case NSCD_CFG_LIST_NSW_DB:
+
+ num = _nscd_cfg_num_nsw_db;
+ l = &_nscd_cfg_nsw_db[0];
+ break;
+
+ case NSCD_CFG_LIST_NSW_SRC:
+
+ num = _nscd_cfg_num_nsw_src_all;
+ l = _nscd_cfg_nsw_src_all;
+ break;
+
+ case NSCD_CFG_LIST_PARAM:
+
+ num = _nscd_cfg_num_param;
+ pl = &_nscd_cfg_param_desc[0];
+ break;
+
+ case NSCD_CFG_LIST_STAT:
+
+ num = _nscd_cfg_num_stat;
+ sl = &_nscd_cfg_stat_desc[0];
+ break;
+
+ default:
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "invalid argument: type (%d)\n", type);
+
+ return (NSCD_INVALID_ARGUMENT);
+ break;
+ }
+
+ size = sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1);
+
+ ret = calloc(1, size);
+ if (ret == NULL)
+ return (NSCD_NO_MEMORY);
+
+ ret->num = num;
+ p = (char *)ret + sizeof (nscd_cfg_list_t);
+ ret->list = (nscd_cfg_id_t **)p;
+
+ if (type == NSCD_CFG_LIST_PARAM) {
+ for (i = 0; i <= num; i++)
+ ret->list[i] = (nscd_cfg_id_t *)&pl[i];
+ } else if (type == NSCD_CFG_LIST_STAT) {
+ for (i = 0; i <= num; i++)
+ ret->list[i] = (nscd_cfg_id_t *)&sl[i];
+ } else {
+ for (i = 0; i <= num; i++)
+ ret->list[i] = &l[i];
+ }
+
+ *list = ret;
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_cfg_get_param_desc_list(
+ nscd_cfg_param_desc_list_t **list)
+{
+ return (_nscd_cfg_get_list((nscd_cfg_list_t **)list,
+ NSCD_CFG_LIST_PARAM));
+}
+
+/* find function pointer in the executable via dlopen(0) */
+static nscd_rc_t
+_nscd_cfg_init_funcs(
+ char *name,
+ void **func_p,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_init_funcs";
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+ static void *handle = NULL;
+ void *sym;
+ nscd_rc_t rc = NSCD_SUCCESS;
+
+ if (name == NULL && handle != NULL) {
+ (void) dlclose(handle);
+ return (rc);
+ }
+ if (name == NULL)
+ return (rc);
+
+ if (handle == NULL) {
+ handle = dlopen((const char *)0, RTLD_LAZY);
+ if (handle == NULL) {
+
+ rc = NSCD_CFG_DLOPEN_ERROR;
+ (void) snprintf(msg, sizeof (msg),
+ gettext("unable to dlopen the nscd executable: %s"),
+ dlerror());
+ goto error_exit;
+ }
+ }
+
+ if (func_p) {
+ if ((sym = dlsym(handle, name)) == NULL) {
+
+ rc = NSCD_CFG_DLSYM_ERROR;
+ (void) snprintf(msg, sizeof (msg),
+gettext("unable to get the address of a symbol in the nscd executable: %s"),
+ dlerror());
+ goto error_exit;
+ } else
+ (void) memcpy(func_p, &sym, sizeof (void *));
+ }
+
+ return (rc);
+
+ error_exit:
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ return (rc);
+}
+
+
+/*
+ * FUNCTION: _nscd_cfg_create_paramDB
+ *
+ * Create the internal config parameter database
+ */
+static nscd_db_t *
+_nscd_cfg_create_paramDB()
+{
+
+ nscd_db_t *ret;
+
+ (void) rw_wrlock(&cfg_paramDB_rwlock);
+
+ ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM);
+
+ if (ret != NULL)
+ cfg_paramDB = ret;
+
+ (void) rw_unlock(&cfg_paramDB_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_cfg_add_index_entry
+ *
+ * Add a config index entry (a name to index mapping)
+ * to the internal configuration database.
+ */
+static nscd_rc_t
+_nscd_cfg_add_index_entry(
+ char *name,
+ int index,
+ nscd_cfg_list_type_t type)
+{
+ int *idx;
+ int size;
+ int dbe_type;
+ nscd_db_entry_t *db_entry;
+
+ if (name == NULL)
+ return (NSCD_INVALID_ARGUMENT);
+
+ if (type == NSCD_CFG_LIST_NSW_DB)
+ dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
+ else if (type == NSCD_CFG_LIST_NSW_SRC)
+ dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
+ else if (type == NSCD_CFG_LIST_PARAM)
+ dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
+ else if (type == NSCD_CFG_LIST_STAT)
+ dbe_type = NSCD_DATA_CFG_STAT_INDEX;
+
+ size = sizeof (int);
+
+ db_entry = _nscd_alloc_db_entry(dbe_type, (const char *)name,
+ size, 1, 1);
+ if (db_entry == NULL)
+ return (NSCD_NO_MEMORY);
+
+ idx = (int *)*(db_entry->data_array);
+ *idx = index;
+
+ (void) rw_wrlock(&cfg_paramDB_rwlock);
+ (void) _nscd_add_db_entry(cfg_paramDB, name, db_entry,
+ NSCD_ADD_DB_ENTRY_FIRST);
+ (void) rw_unlock(&cfg_paramDB_rwlock);
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * FUNCTION: _nscd_cfg_get_index
+ *
+ * Get the index of a config data item by searching the internal config
+ * database. Do not free the returned data.
+ */
+static int
+_nscd_cfg_get_index(
+ char *name,
+ nscd_cfg_list_type_t type)
+{
+ int index = -1, dbe_type;
+ const nscd_db_entry_t *db_entry;
+
+ if (name == NULL)
+ return (-1);
+
+ if (type == NSCD_CFG_LIST_NSW_DB)
+ dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
+ else if (type == NSCD_CFG_LIST_NSW_SRC)
+ dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
+ else if (type == NSCD_CFG_LIST_PARAM)
+ dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
+ else if (type == NSCD_CFG_LIST_STAT)
+ dbe_type = NSCD_DATA_CFG_STAT_INDEX;
+ else
+ return (-1);
+
+ db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type,
+ (const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0);
+
+ if (db_entry != NULL)
+ index = *(int *)*(db_entry->data_array);
+
+ return (index);
+}
+
+static nscd_rc_t
+_nscd_cfg_verify_group_info(
+ nscd_cfg_group_info_t *g_info,
+ nscd_cfg_param_desc_t *gdesc)
+{
+
+ char *me = "_nscd_cfg_verify_group_info";
+ void *vp;
+ nscd_cfg_group_info_t *gi;
+
+ if (_nscd_cfg_flag_is_set(gdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) {
+ vp = (char *)&nscd_cfg_global_default +
+ gdesc->g_offset;
+ gi = (nscd_cfg_group_info_t *)vp;
+ } else {
+ vp = (char *)&nscd_cfg_nsw_db_data_default +
+ gdesc->g_offset;
+ gi = (nscd_cfg_group_info_t *)vp;
+
+ }
+
+ if (g_info->num_param == gi->num_param &&
+ _nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap))
+ return (NSCD_SUCCESS);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: group (%s) info mismatched: group info "
+ "(%d, %#6.4x) not equal to that of default configuration data "
+ "(%d, %#6.4x)\n", gdesc->id.name, g_info->num_param,
+ _nscd_cfg_bitmap_value(g_info->bitmap), gi->num_param,
+ _nscd_cfg_bitmap_value(gi->bitmap));
+
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+
+}
+
+
+static nscd_rc_t
+_nscd_cfg_init_nsw()
+{
+ char *me = "_nscd_cfg_init_nsw";
+ int i, j, idx, rc, num;
+ nscd_cfg_id_t *id;
+ nscd_cfg_list_type_t type[2] = { NSCD_CFG_LIST_NSW_DB,
+ NSCD_CFG_LIST_NSW_SRC };
+
+ nscd_cfg_id_t *list[2] = { _nscd_cfg_nsw_db, NULL};
+
+ list[1] = _nscd_cfg_nsw_src_all;
+
+ for (j = 0; j < 2; j++) {
+
+ if (j == 0)
+ num = _nscd_cfg_num_nsw_db + 1;
+ else
+ num = _nscd_cfg_num_nsw_src_all;
+
+ for (i = 0; i < num; i++) {
+
+ /*
+ * _nscd_cfg_nsw_alldb is the id for the
+ * special ALLDB (defaults for all db)
+ */
+ if (j == 0 && i == _nscd_cfg_num_nsw_db) {
+ id = &_nscd_cfg_nsw_alldb;
+ idx = NSCD_CFG_NSW_ALLDB_INDEX;
+ } else {
+ id = &(list[j])[i];
+ id->index = idx = i;
+ }
+
+ if (id->name == NULL)
+ continue;
+
+ if ((rc = _nscd_cfg_add_index_entry(id->name,
+ idx, type[j])) != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to add index entry for "
+ "nsswitch entry %s\n", id->name);
+
+ _nscd_free_db(cfg_paramDB);
+ return (rc);
+ }
+ }
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * get the address of a function in the nscd executable
+ * and store it in where 'dest_p' points to
+ */
+static nscd_rc_t
+_nscd_cfg_get_funcp(
+ char *name,
+ void *dest_p,
+ void **gfunc_a,
+ nscd_cfg_error_t **errorp)
+{
+
+ void *func;
+ nscd_rc_t rc;
+
+ if (gfunc_a != NULL) {
+
+ if (strcmp(name, NSCD_CFG_FUNC_NAME_AS_GROUP) == 0)
+ (void) memcpy(dest_p, gfunc_a, sizeof (void *));
+
+ return (NSCD_SUCCESS);
+ }
+
+ rc = _nscd_cfg_init_funcs(name, &func, errorp);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ (void) memcpy(dest_p, &func, sizeof (func));
+
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+_nscd_cfg_init_param()
+{
+ char *me = "_nscd_cfg_init_param";
+ int i, gi, fn = 0;
+ nscd_cfg_id_t *id;
+ nscd_cfg_param_desc_t *desc, *gdesc = NULL;
+ nscd_cfg_group_info_t g_info;
+ nscd_cfg_list_type_t type = NSCD_CFG_LIST_PARAM;
+ nscd_rc_t rc;
+ void *nfunc, *vfunc;
+
+ if (_nscd_cfg_create_paramDB() == NULL)
+ return (NSCD_NO_MEMORY);
+
+ desc = &_nscd_cfg_param_desc[0];
+
+ /*
+ * need to loop to the last (+1) param description
+ * which is a fake group and which marks the end
+ * of list. It is used to signal the end of the
+ * previous group so that the proper data will be
+ * set for that group
+ */
+ for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) {
+
+ id = (nscd_cfg_id_t *)desc;
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_GROUP)) {
+
+ if (gdesc != NULL) {
+ g_info.num_param = fn;
+ gdesc->p_fn = fn;
+
+ if ((rc = _nscd_cfg_verify_group_info(
+ &g_info, gdesc)) != NSCD_SUCCESS)
+ return (rc);
+ }
+
+ gi = i;
+ fn = 0;
+ gdesc = desc;
+ g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
+ nfunc = NULL;
+ vfunc = NULL;
+
+ /*
+ * set the notify/verify functions
+ */
+ if (gdesc->nfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(gdesc->nfunc_name,
+ &gdesc->notify, NULL, NULL);
+ if (rc != NULL)
+ return (rc);
+ nfunc = (void *)gdesc->notify;
+ }
+ if (gdesc->vfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(gdesc->vfunc_name,
+ &gdesc->verify, NULL, NULL);
+ if (rc != NULL)
+ return (rc);
+ vfunc = (void *)gdesc->verify;
+ }
+ } else {
+ if (i == 0) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: first parameter "
+ "description is not for a group\n");
+
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+ }
+
+ /*
+ * set bitmap: the rightmost bit represents
+ * the first member (index = 0) in the group,
+ * the next bit is for the second member
+ * (index = 1), and so on
+ */
+ _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
+
+ desc->p_fn = fn++;
+
+ /*
+ * set the notify/verify functions
+ */
+ if (desc->nfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(desc->nfunc_name,
+ &desc->notify, &nfunc, NULL);
+ if (rc != NULL)
+ return (rc);
+ }
+ if (desc->vfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(desc->vfunc_name,
+ &desc->verify, &vfunc, NULL);
+ if (rc != NULL)
+ return (rc);
+ }
+ }
+
+ /* if end of list reached, we are done */
+ if (i == _nscd_cfg_num_param)
+ break;
+
+ desc->g_index = gi;
+
+ id->index = i;
+
+ if ((rc = _nscd_cfg_add_index_entry(id->name,
+ i, type)) != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to add index entry for parameter "
+ "%s\n", id->name);
+
+ _nscd_free_db(cfg_paramDB);
+ return (rc);
+ } else {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "index entry for parameter "
+ "%s added\n", id->name);
+ }
+ }
+
+ return (_nscd_cfg_init_nsw());
+}
+
+static nscd_rc_t
+_nscd_cfg_init_stat()
+{
+ char *me = "_nscd_cfg_init_stat";
+ int i, gi, fn = 0;
+ nscd_cfg_id_t *id;
+ nscd_cfg_stat_desc_t *desc, *gdesc = NULL;
+ nscd_cfg_group_info_t g_info;
+ nscd_cfg_list_type_t type = NSCD_CFG_LIST_STAT;
+ nscd_rc_t rc;
+ void *gsfunc;
+
+ desc = &_nscd_cfg_stat_desc[0];
+
+ /*
+ * need to loop to the last (+1) stat description
+ * which is a fake group and which marks the end
+ * of list. It is used to signal the end of the
+ * previous group so that the proper data will be
+ * set for that group
+ */
+ for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) {
+
+ id = (nscd_cfg_id_t *)desc;
+
+ if (_nscd_cfg_flag_is_set(desc->sflag,
+ NSCD_CFG_SFLAG_GROUP)) {
+
+ if (gdesc != NULL) {
+ g_info.num_param = fn;
+ gdesc->s_fn = fn;
+
+ if (g_info.num_param !=
+ gdesc->gi.num_param ||
+ !_nscd_cfg_bitmap_is_equal(
+ g_info.bitmap, gdesc->gi.bitmap)) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: group (%s) "
+ "info mismatched: "
+ "group info (%d, %#6.4x) not "
+ "equal to the predefined one "
+ "(%d, %#6.4x)\n", gdesc->id.name,
+ g_info.num_param,
+ _nscd_cfg_bitmap_value(g_info.bitmap),
+ gdesc->gi.num_param,
+ _nscd_cfg_bitmap_value(
+ gdesc->gi.bitmap));
+
+ exit(1);
+ return (NSCD_CFG_STAT_DESC_ERROR);
+ }
+ }
+
+ gi = i;
+ fn = 0;
+ gdesc = desc;
+ g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
+ gsfunc = NULL;
+
+ /*
+ * set the get_stat function
+ */
+ if (gdesc->gsfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(gdesc->gsfunc_name,
+ &gdesc->get_stat, NULL, NULL);
+ if (rc != NULL)
+ return (rc);
+ gsfunc = (void *)gdesc->get_stat;
+ }
+ } else {
+ if (i == 0) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: first stat "
+ "description is not for a group\n");
+
+ return (NSCD_CFG_STAT_DESC_ERROR);
+ }
+
+ /*
+ * set bitmap: the rightmost bit represents
+ * the first member (index = 0) in the group,
+ * the next bit is for the second member
+ * (index = 1), and so on
+ */
+ _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
+
+ desc->s_fn = fn++;
+
+ /*
+ * set the get_stat function
+ */
+ if (desc->gsfunc_name != NULL) {
+ rc = _nscd_cfg_get_funcp(desc->gsfunc_name,
+ &desc->get_stat, &gsfunc, NULL);
+ if (rc != NULL)
+ return (rc);
+ }
+ }
+
+ /* if end of list reached, we are done */
+ if (i == _nscd_cfg_num_stat)
+ break;
+
+ desc->g_index = gi;
+
+ id->index = i;
+
+ if ((rc = _nscd_cfg_add_index_entry(id->name,
+ i, type)) != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to add index entry for stat "
+ "description %s\n", id->name);
+
+ _nscd_free_db(cfg_paramDB);
+ return (rc);
+ } else {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "index entry for stat description "
+ "%s added\n", id->name);
+ }
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+_nscd_cfg_copy_vlen_data(
+ void *data,
+ void **new_data_p,
+ nscd_cfg_param_desc_t *desc,
+ int *data_len,
+ nscd_bool_t in)
+{
+ int len, dlen;
+ nscd_cfg_vlen_data_t *v = NULL;
+
+ *new_data_p = NULL;
+ *data_len = 0;
+
+ /* it is OK if there is nothing to copy */
+ if (data == NULL)
+ return (NSCD_SUCCESS);
+
+ /*
+ * if copy to the config store we need to allocate space
+ * for the extra vlen header
+ */
+ if (desc->type == NSCD_CFG_DATA_STRING) {
+ len = dlen = strlen((char *)data) + 1;
+ if (in == nscd_true)
+ len += sizeof (nscd_cfg_vlen_data_t);
+ } else {
+ /*
+ * should not be here, since for now
+ * only string variable length data
+ * is supported
+ */
+ *new_data_p = NULL;
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+ }
+
+ v = calloc(1, len);
+ if (v == NULL) {
+ *new_data_p = NULL;
+ return (NSCD_NO_MEMORY);
+ }
+
+ /*
+ * if copy to the config store, set up
+ * the extra vlen header in which the
+ * pointer to, and length of, the real
+ * data are kept. The pointer to the real
+ * data, not the vlen header, is returned.
+ */
+ if (in == nscd_true) {
+ v->ptr = (char *)v + sizeof (nscd_cfg_vlen_data_t);
+ v->len = dlen;
+ (void) memcpy(v->ptr, data, dlen);
+ *new_data_p = v->ptr;
+ } else {
+ (void) memcpy(v, data, dlen);
+ *new_data_p = v;
+ }
+ *data_len = dlen;
+
+ return (NSCD_SUCCESS);
+}
+
+static void
+_nscd_cfg_free_vlen_data_int(
+ void *data)
+{
+ nscd_cfg_vlen_data_t *v = NULL;
+ void *p;
+
+ if (data == NULL)
+ return;
+
+ p = (char *)data - sizeof (nscd_cfg_vlen_data_t);
+ v = (nscd_cfg_vlen_data_t *)p;
+ if (v->ptr == data)
+ free(v);
+}
+
+static nscd_rc_t
+_nscd_cfg_set_vlen_data_int(
+ void *src,
+ void *dest,
+ nscd_bool_t global)
+{
+ int i, offset, dlen = 0;
+ void *s, *d, *new;
+ void *cptr;
+ nscd_rc_t rc;
+ nscd_cfg_param_desc_t *desc;
+
+ desc = &_nscd_cfg_param_desc[0];
+ for (i = 0; i < _nscd_cfg_num_param; i++, desc++) {
+
+ if (global == nscd_true &&
+ _nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL))
+ continue;
+ else if (global != nscd_true &&
+ _nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL))
+ continue;
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA)) {
+
+ offset = desc->g_offset + desc->p_offset;
+
+ s = (char *)src + offset;
+ cptr = *(char **)s;
+
+ rc = _nscd_cfg_copy_vlen_data(cptr, &new,
+ desc, &dlen, nscd_true);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ d = (char *)dest + offset;
+ /* free the old vlen data */
+ if (*(char **)d == NULL)
+ _nscd_cfg_free_vlen_data_int(*(char **)d);
+
+ *(char **)d = new;
+ }
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static void *
+_nscd_cfg_locate_vlen_data(
+ void *cfg_data,
+ int *len)
+{
+ void *ptr, *ret;
+
+ ptr = *(char **)cfg_data;
+ ret = ptr;
+ if (ret == NULL) {
+ *len = 0;
+ return (NULL);
+ }
+ ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t);
+ *len = ((nscd_cfg_vlen_data_t *)ptr)->len;
+
+ return (ret);
+}
+
+static void
+_nscd_cfg_lock(
+ nscd_bool_t is_read,
+ nscd_cfg_lock_t *cfglock)
+{
+
+ int (*lockfunc)(rwlock_t *);
+
+ if (cfglock == NULL)
+ return;
+
+ if (is_read == nscd_true)
+ lockfunc = rw_rdlock;
+ else
+ lockfunc = rw_wrlock;
+
+ if (cfglock->global != NULL) {
+
+ (lockfunc)(cfglock->global);
+ return;
+ }
+
+ if (cfglock->alldb != NULL)
+ (lockfunc)(cfglock->alldb);
+
+ if (cfglock->nswdb != NULL)
+ (lockfunc)(cfglock->nswdb);
+}
+
+static void
+_nscd_cfg_unlock(
+ nscd_cfg_lock_t *cfglock)
+{
+ if (cfglock == NULL)
+ return;
+
+ if (cfglock->global != NULL) {
+
+ (void) rw_unlock(cfglock->global);
+ free(cfglock);
+ return;
+ }
+
+ if (cfglock->nswdb != NULL)
+ (void) rw_unlock(cfglock->nswdb);
+
+ if (cfglock->alldb != NULL)
+ (void) rw_unlock(cfglock->alldb);
+
+ free(cfglock);
+}
+
+/*
+ * If vlen_data_addr is given, it will be set to the
+ * address of the pointer pointing to the vlen data.
+ * 'cfglock' will be set to point to the reader/writer
+ * lock(s) protecting the (group) configuration data.
+ */
+static nscd_rc_t
+_nscd_cfg_locate_cfg_data(
+ void **cfg_data,
+ nscd_bool_t is_read,
+ nscd_cfg_param_desc_t *desc,
+ nscd_cfg_id_t *nswdb,
+ nscd_bool_t get_group,
+ void **vlen_data_addr,
+ int *len,
+ nscd_cfg_lock_t **cfglock)
+{
+ int offset;
+
+ *cfg_data = NULL;
+ if (len != NULL)
+ *len = 0;
+ if (vlen_data_addr != NULL)
+ *vlen_data_addr = NULL;
+
+ if (cfglock != NULL) {
+ *cfglock = calloc(1, sizeof (nscd_cfg_lock_t));
+ if (*cfglock == NULL)
+ return (NSCD_NO_MEMORY);
+ }
+
+ /* assume if nswdb is NULL, the param is a global one */
+ if (nswdb == NULL) {
+
+ offset = desc->g_offset;
+ if (get_group != nscd_true)
+ offset += desc->p_offset;
+ *cfg_data = (char *)nscd_cfg_global_current + offset;
+
+ if (cfglock != NULL)
+ (*cfglock)->global = nscd_cfg_global_rwlock;
+
+ } else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) {
+
+ offset = desc->g_offset;
+ if (get_group != nscd_true)
+ offset += desc->p_offset;
+ *cfg_data = (char *)nscd_cfg_nsw_alldb_current +
+ offset;
+
+ if (cfglock != NULL)
+ (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
+
+ } else {
+
+ offset = nswdb->index *
+ (sizeof (nscd_cfg_nsw_db_data_t)) + desc->g_offset;
+ if (get_group != nscd_true)
+ offset += desc->p_offset;
+ *cfg_data = (char *)nscd_cfg_nsw_db_data_current +
+ offset;
+
+ if (cfglock != NULL) {
+ (*cfglock)->nswdb =
+ &nscd_cfg_nsw_db_data_rwlock[nswdb->index];
+
+ (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
+ }
+ }
+
+ /* lock the config data */
+ if (cfglock != NULL)
+ _nscd_cfg_lock(is_read, *cfglock);
+
+ if (get_group != nscd_true &&
+ _nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_GROUP) &&
+ (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA))) {
+ if (vlen_data_addr != NULL)
+ *vlen_data_addr = *cfg_data;
+ *cfg_data = _nscd_cfg_locate_vlen_data(*cfg_data, len);
+ return (NSCD_SUCCESS);
+ }
+
+ if (len != NULL) {
+ if (get_group == nscd_true)
+ *len = desc->g_size;
+ else
+ *len = desc->p_size;
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * perform the preliminary (range) check on 'data' based on the
+ * datatype (desc->datatype) of the config parameter
+ */
+nscd_rc_t
+_nscd_cfg_prelim_check(
+ nscd_cfg_param_desc_t *desc,
+ void *data,
+ nscd_cfg_error_t **errorp)
+{
+
+ char *me = "_nscd_cfg_prelim_check";
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+ nscd_cfg_str_check_t *sc;
+ nscd_cfg_int_check_t *ic;
+ nscd_cfg_bitmap_check_t *bmc;
+ nscd_rc_t rc = NSCD_CFG_PRELIM_CHECK_FAILED;
+
+ if ((nscd_cfg_str_check_t *)desc->p_check == NULL)
+ return (NSCD_SUCCESS);
+
+ switch (desc->type) {
+
+ case NSCD_CFG_DATA_STRING:
+
+ sc = (nscd_cfg_str_check_t *)desc->p_check;
+ if (sc->must_not_null == nscd_true && data == NULL) {
+
+ if (errorp == NULL)
+ break;
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("data must be specified for %s"),
+ desc->id.name);
+
+ break;
+ }
+
+ if (data == NULL) {
+ rc = NSCD_SUCCESS;
+ break;
+ }
+
+ if (sc->maxlen != 0 &&
+ strlen((char *)data) > sc->maxlen) {
+
+ if (errorp == NULL)
+ break;
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("length of data (%s) for %s larger than %d"),
+ (char *)data, desc->id.name, sc->maxlen);
+ break;
+ }
+
+ rc = NSCD_SUCCESS;
+
+ break;
+
+ case NSCD_CFG_DATA_INTEGER:
+
+ ic = (nscd_cfg_int_check_t *)desc->p_check;
+ if (*(int *)data > ic->max ||
+ *(int *)data < ic->min) {
+
+ if (errorp == NULL)
+ break;
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("data (%d) for %s out of range (%d - %d)"),
+ *(int *)data, desc->id.name,
+ ic->min, ic->max);
+
+ break;
+ }
+
+ rc = NSCD_SUCCESS;
+
+ break;
+
+ case NSCD_CFG_DATA_BITMAP:
+
+ bmc = (nscd_cfg_bitmap_check_t *)desc->p_check;
+ if (_nscd_cfg_bitmap_value(*(nscd_cfg_bitmap_t *)data) &
+ ~(bmc->valid_bits)) {
+
+ if (errorp == NULL)
+ break;
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("data (%#6.4x) for %s contain bit not in 0x%x"),
+ _nscd_cfg_bitmap_value(
+ *(nscd_cfg_bitmap_t *)data),
+ desc->id.name,
+ _nscd_cfg_bitmap_value(bmc->valid_bits));
+ break;
+ }
+
+ rc = NSCD_SUCCESS;
+
+ break;
+ }
+
+ if (rc != NSCD_SUCCESS && errorp != NULL) {
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid argument: %s\n", (*errorp)->msg);
+ }
+
+ return (rc);
+}
+
+static nscd_rc_t
+_nscd_cfg_notify_i(
+ nscd_cfg_param_desc_t *desc,
+ nscd_cfg_id_t *nswdb,
+ int *skip,
+ nscd_cfg_error_t **errorp)
+{
+
+ char *me = "_nscd_cfg_notify_i";
+ int i, num, skip_bk;
+ void *cfg_data, *cdata;
+ void *cookie = NULL;
+ nscd_rc_t rc;
+ nscd_cfg_flag_t dflag, dflag1;
+ nscd_cfg_bitmap_t bitmap_c, bitmap_s, *bitmap_addr;
+ nscd_cfg_group_info_t *gi;
+
+ if (errorp != NULL)
+ *errorp = NULL;
+
+ if (skip == NULL)
+ skip = &skip_bk;
+
+ *skip = 0;
+
+ if (_nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_GROUP)) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: expect parameter description for group, "
+ "but receive parameter description is for %s\n",
+ desc->id.name);
+
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+ }
+
+ /*
+ * Set data flag going with data to be sent to the
+ * verify/notify routines. Allowing the config flag
+ * be exipandable, set the bits one by one.
+ */
+ dflag = NSCD_CFG_FLAG_ZERO;
+ dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
+ dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_INIT);
+ dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_INIT_SET_ALL_DB))
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_SET_ALL_DB);
+
+ /* get to the group data in the config store */
+ rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true,
+ desc, nswdb, nscd_true, NULL, NULL, NULL);
+ if (rc != NSCD_SUCCESS)
+ goto error;
+
+ /*
+ * the static bitmap associated with the group
+ * may be replaced before sending to the components,
+ * so save the bitmap for later use
+ */
+ gi = _nscd_cfg_get_gi(cfg_data);
+ bitmap_c = gi->bitmap;
+ bitmap_addr = &(gi->bitmap);
+
+ /*
+ * the elements in this group will all be handled
+ * so the caller can skip them
+ */
+ *skip = desc->p_fn;
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
+ /* send the entire group just once */
+ num = 1;
+
+ else { /* send individual members one by one */
+
+ num = desc->p_fn;
+
+ /*
+ * skip the first desc which is for the group
+ * and get to the desc for the first member
+ */
+ desc++;
+
+ dflag = _nscd_cfg_flag_unset(dflag,
+ NSCD_CFG_DFLAG_GROUP);
+ }
+
+ dflag1 = dflag;
+ for (i = 0; i < num; i++, desc++) {
+
+ dflag = dflag1;
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
+
+ /* set the bitmap to select just this member */
+ bitmap_s = NSCD_CFG_BITMAP_ZERO;
+ _nscd_cfg_bitmap_set_nth(bitmap_s, i);
+ /* replace the bitmap in the cfg data */
+ _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
+
+ /*
+ * send the whole group but with only one
+ * member selected
+ */
+ cdata = cfg_data;
+
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_GROUP);
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_BIT_SELECTED);
+ } else {
+ /*
+ * send param data or group data:
+ * param data - non-xero desc->p_offset
+ * group data - zero desc->p_offset
+ */
+ cdata = (char *)cfg_data + desc->p_offset;
+
+ /*
+ * if variable length data, need to send pointer
+ * to the data (not the address of the pointer)
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA))
+ cdata = *(char **)cdata;
+ }
+
+ if (desc->verify != NULL) {
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_VERIFY);
+ rc = desc->verify(cdata, desc, nswdb,
+ dflag, errorp, &cookie);
+ if (rc != NSCD_SUCCESS)
+ goto error;
+ }
+
+ if (desc->notify != NULL) {
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_NOTIFY);
+
+ rc = desc->notify(cfg_data, desc, nswdb,
+ dflag, errorp, cookie);
+ if (rc != NSCD_SUCCESS)
+ goto error;
+ }
+ }
+
+ rc = NSCD_SUCCESS;
+
+ /* restore the bitmap in the cfg data */
+ _nscd_cfg_bitmap_set(bitmap_addr, bitmap_c);
+
+ error:
+
+ return (rc);
+
+}
+
+static nscd_rc_t
+_nscd_cfg_notify_init(
+ nscd_cfg_error_t **errorp)
+{
+ int i, j, skip;
+ nscd_rc_t rc;
+ nscd_cfg_id_t *nswdb = NULL;
+ nscd_cfg_param_desc_t *desc;
+
+ if (errorp != NULL)
+ *errorp = NULL;
+
+ for (i = 0; i < _nscd_cfg_num_param; i++) {
+
+ desc = &_nscd_cfg_param_desc[i];
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */
+
+ rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp);
+ } else {
+
+ /*
+ * if use defaults for all nsswitch database,
+ * send the config data to verify/notify once
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) {
+
+ nswdb = &_nscd_cfg_nsw_alldb;
+
+ rc = _nscd_cfg_notify_i(desc, nswdb,
+ &skip, errorp);
+ } else { /* send data once for each nsw db */
+
+ for (j = 0; j < _nscd_cfg_num_nsw_db;
+ j++) {
+
+ nswdb = &_nscd_cfg_nsw_db[j];
+
+ rc = _nscd_cfg_notify_i(desc,
+ nswdb, &skip, errorp);
+ }
+ }
+ }
+
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ i += skip;
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_cfg_init(
+ nscd_cfg_error_t **errorp)
+{
+
+ int i, j, datalen;
+ int dbi = 0, dbj = 0;
+ char *dest, *src;
+ char *dbni = NULL, *dbnj = NULL;
+ nscd_rc_t rc;
+ nscd_cfg_nsw_spc_default_t *spc;
+
+ if (errorp != NULL)
+ *errorp = NULL;
+
+ rc = _nscd_cfg_init_param();
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ rc = _nscd_cfg_init_stat();
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ nscd_cfg_global_current = calloc(1,
+ sizeof (nscd_cfg_global_data_t));
+ if (nscd_cfg_global_current == NULL)
+ return (NSCD_NO_MEMORY);
+
+ nscd_cfg_nsw_alldb_current = calloc(1,
+ sizeof (nscd_cfg_nsw_db_data_t));
+ if (nscd_cfg_nsw_alldb_current == NULL)
+ return (NSCD_NO_MEMORY);
+
+ nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db,
+ sizeof (nscd_cfg_nsw_db_data_t));
+ if (nscd_cfg_nsw_db_data_current == NULL)
+ return (NSCD_NO_MEMORY);
+
+ nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t));
+ if (nscd_cfg_global_rwlock == NULL)
+ return (NSCD_NO_MEMORY);
+ (void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL);
+
+ *nscd_cfg_global_current = nscd_cfg_global_default;
+
+ rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default,
+ nscd_cfg_global_current, nscd_true);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db,
+ sizeof (rwlock_t));
+ if (nscd_cfg_nsw_db_data_rwlock == NULL)
+ return (NSCD_NO_MEMORY);
+
+ /* set per switch db config to the default for all db's */
+ for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
+
+ nscd_cfg_nsw_db_data_current[i] =
+ nscd_cfg_nsw_db_data_default;
+
+ (void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i],
+ NULL, NULL);
+ }
+
+ /* add db specific defaults */
+ for (i = 0; i < _nscd_cfg_num_nsw_default; i++) {
+
+ if (_nscd_cfg_nsw_spc_default[i].data == NULL)
+ continue;
+
+ if (_nscd_cfg_nsw_spc_default[i].db != dbni) {
+ for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
+
+ if (strcmp(_nscd_cfg_nsw_db[j].name,
+ _nscd_cfg_nsw_spc_default[i].db) != 0)
+ continue;
+
+ dbi = _nscd_cfg_nsw_db[j].index;
+ dbni = _nscd_cfg_nsw_db[j].name;
+ break;
+ }
+ }
+
+ dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
+ _nscd_cfg_nsw_spc_default[i].group_off +
+ _nscd_cfg_nsw_spc_default[i].param_off;
+
+ src = _nscd_cfg_nsw_spc_default[i].data;
+ datalen = _nscd_cfg_nsw_spc_default[i].data_len;
+
+ (void) memcpy(dest, src, datalen);
+ }
+
+ /* add db specific defaults via links */
+ for (i = 0; i < _nscd_cfg_num_link_default; i++) {
+
+ if (_nscd_cfg_nsw_link_default[i].data == NULL)
+ continue;
+
+ spc = _nscd_cfg_nsw_link_default[i].data;
+
+ if (_nscd_cfg_nsw_link_default[i].db != dbni) {
+ for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
+
+ if (strcmp(_nscd_cfg_nsw_db[j].name,
+ _nscd_cfg_nsw_link_default[i].db) != 0)
+ continue;
+
+ dbi = _nscd_cfg_nsw_db[j].index;
+ dbni = _nscd_cfg_nsw_db[j].name;
+ break;
+ }
+ }
+
+ dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
+ _nscd_cfg_nsw_link_default[i].group_off +
+ _nscd_cfg_nsw_link_default[i].param_off;
+
+ if (_nscd_cfg_nsw_db[j].name != dbnj) {
+ for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
+
+ if (strcmp(spc->db,
+ _nscd_cfg_nsw_db[j].name) != 0)
+ continue;
+
+ dbnj = _nscd_cfg_nsw_db[j].name;
+ dbj = _nscd_cfg_nsw_db[j].index;
+ break;
+ }
+ }
+
+ src = (char *)&nscd_cfg_nsw_db_data_current[dbj] +
+ spc->group_off + spc->param_off;
+ datalen = spc->data_len;
+
+ (void) memcpy(dest, src, datalen);
+ }
+
+ /* fix up variable length fields */
+ for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
+
+ rc = _nscd_cfg_set_vlen_data_int(
+ &nscd_cfg_nsw_db_data_current[i],
+ &nscd_cfg_nsw_db_data_current[i], nscd_false);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ }
+
+ nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t));
+ if (nscd_cfg_nsw_alldb_rwlock == NULL)
+ return (NSCD_NO_MEMORY);
+
+ (void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL);
+
+ rc = _nscd_cfg_set_vlen_data_int(
+ &nscd_cfg_nsw_db_data_default,
+ &nscd_cfg_nsw_alldb_current, nscd_false);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ /*
+ * notify and send the configuration data to
+ * the nscd components
+ */
+ rc = _nscd_cfg_notify_init(errorp);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+_nscd_cfg_get_handle_common(
+ nscd_cfg_list_type_t type,
+ char *name,
+ char *nswdb_name,
+ nscd_cfg_handle_t **handle,
+ nscd_cfg_error_t **errorp)
+{
+
+ int i, is_global;
+ char *desc_str;
+ nscd_cfg_handle_t *h;
+ nscd_cfg_param_desc_t *pdesc;
+ nscd_cfg_stat_desc_t *sdesc;
+ char *me = "_nscd_cfg_get_handle_common";
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+ nscd_rc_t rc = NSCD_INVALID_ARGUMENT;
+
+ if (handle == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("address of handle not specified"));
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid argument: %s\n", msg);
+
+ return (rc);
+ }
+
+ *handle = NULL;
+
+ if (name == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("name not specified"));
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid argument: %s\n");
+
+ return (rc);
+ }
+
+ h = calloc(1, sizeof (nscd_cfg_handle_t));
+ if (h == NULL)
+ return (NSCD_NO_MEMORY);
+ h->type = type;
+
+ if (type == NSCD_CFG_LIST_PARAM)
+ desc_str = gettext("configuration parameter");
+ else
+ desc_str = gettext("statistics");
+
+ /* get param or stat descriptor */
+ i = _nscd_cfg_get_index(name, type);
+ if (i != -1) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: index of %s is %d\n", desc_str, name, i);
+
+ if (type == NSCD_CFG_LIST_PARAM) {
+ pdesc = &_nscd_cfg_param_desc[i];
+ (void) memcpy(&h->desc, &pdesc, sizeof (pdesc));
+ is_global = _nscd_cfg_flag_is_set(
+ pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL);
+
+ /* hidden params are not exposed */
+ if (_nscd_cfg_flag_is_set(
+ pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN))
+ i = -1;
+
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_OBSOLETE)) {
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_WARNING)
+ (me,
+ gettext("%s: %s is obsolete and will be ignored\n"),
+ desc_str, name);
+ }
+ } else {
+ sdesc = &_nscd_cfg_stat_desc[i];
+ (void) memcpy(&h->desc, &sdesc, sizeof (sdesc));
+ is_global = _nscd_cfg_flag_is_set(
+ sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL);
+ }
+ }
+
+ if (i == -1) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("%s: unknown name \"%s\""), desc_str, name);
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ free(h);
+ return (rc);
+ }
+
+ /*
+ * if the param/stat is not a global one, we need to
+ * know which nsswitch database we are dealing with
+ */
+ if (is_global == 0) {
+ if (nswdb_name == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("%s: switch database name not specified"),
+ desc_str);
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s for non-global param or stat %s\n",
+ msg, name);
+
+ free(h);
+ return (rc);
+ }
+ } else {
+
+ if (nswdb_name != NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("%s: switch database specified for global data"),
+ desc_str);
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s %s\n", msg, name);
+
+ free(h);
+ return (rc);
+ }
+
+ *handle = h;
+ return (NSCD_SUCCESS);
+ }
+
+ /* get nsw DB id */
+ i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB);
+ if (i != -1) {
+
+ if (i == NSCD_CFG_NSW_ALLDB_INDEX)
+ h->nswdb = &_nscd_cfg_nsw_alldb;
+ else
+ h->nswdb = &_nscd_cfg_nsw_db[i];
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s: index of %s is %d\n",
+ desc_str, nswdb_name, i);
+ } else {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("%s: unknown switch database name \"%s\""),
+ desc_str, nswdb_name);
+ if (errorp)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ free(h);
+ return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
+ }
+
+ *handle = h;
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_cfg_get_handle(
+ char *param_name,
+ char *nswdb_name,
+ nscd_cfg_handle_t **handle,
+ nscd_cfg_error_t **errorp)
+{
+
+ return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM,
+ param_name, nswdb_name, handle, errorp));
+}
+
+nscd_rc_t
+_nscd_cfg_get_stat_handle(
+ char *stat_name,
+ char *nswdb_name,
+ nscd_cfg_handle_t **handle,
+ nscd_cfg_error_t **errorp)
+{
+
+ return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT,
+ stat_name, nswdb_name, handle, errorp));
+}
+
+void
+_nscd_cfg_free_handle(
+ nscd_cfg_handle_t *handle)
+{
+
+ free(handle);
+
+}
+
+static void
+_nscd_cfg_free_vlen_data_group(
+ nscd_cfg_param_desc_t *gdesc,
+ void *group_data,
+ nscd_bool_t in)
+{
+ int num;
+ void *dest, *ptr;
+ nscd_cfg_param_desc_t *desc;
+
+ desc = gdesc;
+
+ num = ((nscd_cfg_group_info_t *)group_data)->num_param;
+
+ while (num-- > 0) {
+
+ desc++;
+
+ /* skip fixed length data */
+ if (_nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA))
+ continue;
+
+ dest = (char *)group_data + desc->p_offset;
+ ptr = *(char **)dest;
+ if (ptr == NULL)
+ continue;
+ if (in == nscd_true)
+ _nscd_cfg_free_vlen_data_int(ptr);
+ else
+ free(ptr);
+ }
+}
+
+void
+_nscd_cfg_free_param_data(
+ void *data)
+{
+
+ if (data == NULL)
+ return;
+
+ free(data);
+}
+
+void
+_nscd_cfg_free_group_data(
+ nscd_cfg_handle_t *handle,
+ void *data)
+{
+
+ nscd_cfg_param_desc_t *desc;
+ nscd_cfg_group_info_t *gi;
+
+ if (handle == NULL || data == NULL)
+ return;
+
+ desc = _nscd_cfg_get_desc(handle);
+ gi = (nscd_cfg_group_info_t *)data;
+ if (desc->p_fn != gi->num_param)
+ return;
+
+ _nscd_cfg_free_vlen_data_group(desc, data, nscd_false);
+
+ free(data);
+}
+
+void
+_nscd_cfg_free_error(
+ nscd_cfg_error_t *error)
+{
+
+ if (error == NULL)
+ return;
+
+ free(error);
+}
+
+static nscd_rc_t
+_nscd_cfg_copy_param_data(
+ nscd_cfg_param_desc_t *desc,
+ void *dest,
+ void *pdata,
+ nscd_bool_t in,
+ nscd_bool_t set_addr)
+{
+
+ char *me = "_nscd_cfg_copy_param_data";
+ void *tmp;
+ int dlen;
+ nscd_rc_t rc = NSCD_SUCCESS;
+
+ if (desc == NULL || dest == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "input desc == %p, dest == %p\n", desc, dest);
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ /* fixed length data */
+ if (_nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA)) {
+ (void) memcpy(dest, pdata, desc->p_size);
+ goto done;
+ }
+
+
+ /* variable length data from this point on */
+
+ /* make a copy of the variable length data */
+ rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in);
+ if (rc != NSCD_SUCCESS)
+ goto done;
+
+ if (in == nscd_true) { /* data to internal */
+
+ /* free the variable length data in the config store */
+ if (*(char **)dest != NULL)
+ _nscd_cfg_free_vlen_data_int(*(char **)dest);
+ }
+
+ if (set_addr == nscd_true) {
+ /*
+ * set the addr of the vlen data
+ */
+ *(char **)dest = tmp;
+ } else {
+ /*
+ * copy the data content (not address)
+ */
+ (void) memcpy(dest, tmp, dlen);
+ }
+
+ done:
+
+ return (rc);
+}
+
+static nscd_rc_t
+_nscd_cfg_copy_group_data_in(
+ nscd_cfg_param_desc_t *gdesc,
+ nscd_cfg_group_info_t *gi,
+ void *group_dest,
+ void *group_src)
+{
+ int i, num;
+ nscd_cfg_param_desc_t *desc;
+ void *src, *dest;
+
+ i = 0;
+ num = gi->num_param;
+ desc = gdesc;
+
+ while (num-- > 0) {
+
+ desc++;
+
+ /* if member not selected by bitmap, skip */
+ if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++))
+ continue;
+
+ src = (char *)group_src + desc->p_offset;
+ dest = (char *)group_dest + desc->p_offset;
+
+ /*
+ * if variable length data, free and replace the old
+ * with the new
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA)) {
+ _nscd_cfg_free_vlen_data_int(*(char **)dest);
+ *(char **)dest = *(char **)src;
+ *(char **)src = NULL;
+ } else {
+ /*
+ * fixed length data, just copy it
+ */
+ (void) memcpy(dest, src, desc->p_size);
+ }
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+_nscd_cfg_copy_group_data_out(
+ nscd_cfg_param_desc_t *gdesc,
+ void *group_dest,
+ void *group_src)
+{
+
+ char *me = "_nscd_cfg_copy_group_data_out";
+ void *src, *dest;
+ int dlen;
+ int num;
+ nscd_cfg_group_info_t *gi;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_param_desc_t *desc;
+
+ if (group_dest == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "input group_dest = NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ gi = _nscd_cfg_get_gi(group_src);
+ num = gi->num_param;
+ desc = gdesc;
+
+ while (num-- > 0) {
+
+ desc++;
+
+ dest = (char *)group_dest + desc->p_offset;
+ src = (char *)group_src + desc->p_offset;
+
+ /*
+ * if variable length data, get the real
+ * address and length of the data
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA)) {
+ src = _nscd_cfg_locate_vlen_data(src, &dlen);
+ if (dlen == NULL)
+ continue;
+ }
+
+ /*
+ * The nscd_true asks _nscd_cfg_copy_param_data
+ * to set addr of the vlen data in 'dest' rather
+ * than copying the data content
+ */
+ rc = _nscd_cfg_copy_param_data(desc, dest, src,
+ nscd_false, nscd_true);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to copy param data for %s\n",
+ desc->id.name);
+
+ _nscd_cfg_free_vlen_data_group(gdesc,
+ group_dest, nscd_false);
+
+ free(group_dest);
+
+ return (rc);
+ }
+ }
+
+ /*
+ * set group bitmap
+ */
+ (void) memcpy(group_dest, group_src,
+ sizeof (nscd_cfg_group_info_t));
+
+ return (rc);
+}
+
+
+/*
+ * group_cfg is needed always; group_src may be NULL if
+ * param_index not zero and pdata not NULL; group_cfg and
+ * pdata should not be both non-NULL
+ */
+static nscd_rc_t
+_nscd_cfg_copy_group_data_merge(
+ nscd_cfg_param_desc_t *gdesc,
+ void **group_dest,
+ void *group_src,
+ void *group_cfg,
+ int param_index,
+ void *pdata)
+{
+
+ char *me = "_nscd_cfg_copy_group_data_merge";
+ void *src, *dest, *tmp_dest = NULL;
+ int num, i = 0;
+ nscd_cfg_group_info_t *gi;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_param_desc_t *desc;
+ nscd_cfg_bitmap_t bitmap;
+
+ if (group_dest == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "input **group_dest == NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ if (group_cfg == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "input **group_cfg == NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ if (param_index != NULL && pdata == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "param_index != NULL but pdata == %p\n", pdata);
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ tmp_dest = calloc(1, gdesc->g_size);
+ if (tmp_dest == NULL)
+ return (NSCD_NO_MEMORY);
+
+ if (group_src != NULL)
+ gi = _nscd_cfg_get_gi(group_src);
+ else {
+ gi = _nscd_cfg_get_gi(group_cfg);
+ bitmap = NSCD_CFG_BITMAP_ZERO;
+ }
+
+ num = gi->num_param;
+ desc = gdesc;
+
+ while (num-- > 0) {
+
+ desc++;
+
+ dest = (char *)tmp_dest + desc->p_offset;
+
+ /*
+ * if member not selected by bitmap in group_src,
+ * get the member data in group_cfg
+ */
+ if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) ||
+ group_src == NULL) {
+ src = (char *)group_cfg + desc->p_offset;
+ } else
+ src = (char *)group_src + desc->p_offset;
+
+ if (desc->id.index == param_index) {
+
+ /* use the param data in pdata if provided */
+ src = pdata;
+ _nscd_cfg_bitmap_set_nth(bitmap, i);
+ }
+
+ /*
+ * if variable length data, get to the data
+ * instead of pointer to the data
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA))
+ src = *(char **)src;
+
+ /*
+ * nscd_true asks _nscd_cfg_copy_param_data to
+ * set addr of the vlen data in 'dest' rather
+ * than copying the data content
+ */
+ rc = _nscd_cfg_copy_param_data(desc, dest, src,
+ nscd_true, nscd_true);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to copy param data for %s\n",
+ desc->id.name);
+
+ _nscd_cfg_free_vlen_data_group(gdesc,
+ tmp_dest, nscd_true);
+
+ free(tmp_dest);
+
+ return (rc);
+ }
+ }
+
+ *group_dest = tmp_dest;
+
+ /*
+ * set bitmap: if input is group data, use the one
+ * given; if input is param data, use the one computed
+ * above
+ */
+ if (group_src != NULL)
+ (void) memcpy(*group_dest, group_src,
+ sizeof (nscd_cfg_group_info_t));
+ else {
+ gi = _nscd_cfg_get_gi(*group_dest);
+ _nscd_cfg_bitmap_set(&gi->bitmap, bitmap);
+ }
+
+ return (rc);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_get(
+ nscd_cfg_handle_t *handle,
+ void **data,
+ int *data_len,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_get";
+ int dlen;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_id_t *nswdb;
+ nscd_cfg_param_desc_t *desc;
+ void *cfg_data, *ptr = NULL;
+ nscd_bool_t get_group = nscd_false;
+ nscd_bool_t out = nscd_false;
+ nscd_cfg_lock_t *lock = NULL;
+
+ if (data_len != NULL)
+ *data_len = 0;
+
+ if (data == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "input data = %p\n", data);
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ *data = NULL;
+
+ if (handle == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "handle is NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ nswdb = handle->nswdb;
+ desc = (nscd_cfg_param_desc_t *)handle->desc;
+
+ if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
+ get_group = nscd_true;
+
+ /*
+ * locate the current value of the param or group
+ * and lock the config data for reading
+ */
+ rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc,
+ nswdb, get_group, NULL, &dlen, &lock);
+ if (rc != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to locate config data\n");
+ return (rc);
+
+ } else if (cfg_data == NULL) /* NULL vlen data */
+ goto done;
+
+ ptr = calloc(1, dlen);
+ if (ptr == NULL) {
+ rc = NSCD_NO_MEMORY;
+ goto error_exit;
+ }
+
+ if (get_group == nscd_true) {
+
+ rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to copy group data %p: "
+ "error = %d\n", cfg_data, rc);
+
+ goto error_exit;
+ }
+ } else {
+ /*
+ * nscd_false asks _nscd_cfg_copy_param_data to
+ * copy the data content rather than just setting
+ * the addr of the vlen data in 'ptr'
+ */
+ rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data,
+ out, nscd_false);
+
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to copy param data %p: "
+ "error = %d\n", cfg_data, rc);
+
+ goto error_exit;
+ }
+ }
+
+ *data = ptr;
+
+ done:
+
+ if (data_len != NULL)
+ *data_len = dlen;
+
+ _nscd_cfg_unlock(lock);
+
+ return (NSCD_SUCCESS);
+
+ error_exit:
+
+ _nscd_cfg_unlock(lock);
+ if (ptr != NULL)
+ free(ptr);
+
+ return (rc);
+}
+
+/*
+ * three type of data:
+ * 1 - single param
+ * desc is that of the param
+ * 2 - single param to be sent in a group
+ * a single bit is set in the bitmap,
+ * desc is that of the group
+ * 3 - group data
+ * one of more bits are set in the bitmap,
+ * desc is that of the group
+ */
+static nscd_rc_t
+_nscd_cfg_notify_s(
+ nscd_cfg_param_desc_t *desc,
+ nscd_cfg_id_t *nswdb,
+ void *data,
+ nscd_cfg_error_t **errorp)
+{
+ int i, num, is_group = 0;
+ void *cookie = NULL;
+ void *cdata;
+ nscd_rc_t rc;
+ nscd_cfg_flag_t dflag, dflag1;
+ nscd_cfg_bitmap_t bitmap_s, bitmap_in, *bitmap_addr = NULL;
+ nscd_cfg_group_info_t *gi;
+
+ if (errorp != NULL)
+ *errorp = NULL;
+
+ /*
+ * Set data flag going with data to be sent to the
+ * verify/notify routines. To allow the config flag
+ * be exipandable, set the bits one by one.
+ */
+ dflag = NSCD_CFG_FLAG_ZERO;
+ dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
+ if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
+ dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
+ is_group = 1;
+ }
+ if (nswdb != NULL &&
+ strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0)
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_SET_ALL_DB);
+
+ /*
+ * the bitmap in the input data may be replaced before
+ * sending to the components, so save the bitmap for
+ * later use
+ */
+ if (is_group == 1) {
+ gi = _nscd_cfg_get_gi(data);
+ bitmap_in = gi->bitmap;
+ bitmap_addr = &(gi->bitmap);
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
+ /* send the entire group just once */
+ num = 1;
+
+ else { /* send individual members one by one */
+
+ num = desc->p_fn;
+
+ /*
+ * skip the first desc which is for the group
+ * and get to the desc for the first member
+ */
+ desc++;
+
+ dflag = _nscd_cfg_flag_unset(dflag,
+ NSCD_CFG_DFLAG_GROUP);
+ }
+ } else {
+ /* not group data, send the member once */
+ num = 1;
+ }
+
+ dflag1 = dflag;
+ for (i = 0; i < num; i++, desc++) {
+
+ dflag = dflag1;
+
+ if (is_group == 0) {
+ cdata = data;
+ goto verify_data;
+ }
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
+
+ /* set the bitmap to select just this member */
+ bitmap_s = NSCD_CFG_BITMAP_ZERO;
+ _nscd_cfg_bitmap_set_nth(bitmap_s, i);
+ /* replace the bitmap in the input data */
+ _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
+
+ /*
+ * send the whole group but with only one
+ * member selected
+ */
+ cdata = data;
+
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_GROUP);
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_BIT_SELECTED);
+ } else {
+ /*
+ * send param data or group data:
+ * param data - non-xero desc->p_offset
+ * group data - zero desc->p_offset
+ */
+ cdata = (char *)data + desc->p_offset;
+
+ /*
+ * if variable length data, need to send pointer
+ * to the data (not the address of the pointer)
+ */
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA))
+ cdata = *(char **)cdata;
+ }
+
+ verify_data:
+
+ if (desc->verify != NULL) {
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_VERIFY);
+ rc = desc->verify(cdata, desc, nswdb,
+ dflag, errorp, &cookie);
+ if (rc != NSCD_SUCCESS)
+ goto error_exit;
+ }
+
+ if (desc->notify != NULL) {
+ dflag = _nscd_cfg_flag_set(dflag,
+ NSCD_CFG_DFLAG_NOTIFY);
+
+ rc = desc->notify(data, desc, nswdb,
+ dflag, errorp, cookie);
+ if (rc != NSCD_SUCCESS)
+ goto error_exit;
+ }
+ }
+
+ rc = NSCD_SUCCESS;
+
+ error_exit:
+
+ /* restore the bitmap in the input data */
+ if (bitmap_addr != NULL)
+ _nscd_cfg_bitmap_set(bitmap_addr, bitmap_in);
+
+ return (rc);
+}
+
+/*
+ * Convert string 'str' to data based on the data type in 'desc'.
+ * 'data' points to the buffer in which the converted data
+ * is placed. '*data_p' points to the buffer, or in the case
+ * of a string data type, points to the untoched string (i.e.,
+ * 'str').
+ */
+nscd_rc_t
+_nscd_cfg_str_to_data(
+ nscd_cfg_param_desc_t *desc,
+ char *str,
+ void *data,
+ void **data_p,
+ nscd_cfg_error_t **errorp)
+{
+
+ char *me = "_nscd_cfg_str_to_data";
+ char *c;
+ nscd_cfg_bitmap_t bitmap;
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+ nscd_rc_t rc = NSCD_CFG_DATA_CONVERSION_FAILED;
+
+ if (desc == NULL || str == NULL || data == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: one of the following is NULL "
+ "desc = %p, str = %p, data = %p, data_p = %p\n",
+ desc, str, data, data_p);
+
+ return (NSCD_INVALID_ARGUMENT);
+ }
+ *data_p = data;
+
+ /* if description is that of a group, return error */
+ if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("single data specified for group %s"), desc->id.name);
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
+ msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s)\n", msg);
+
+ return (NSCD_INVALID_ARGUMENT);
+
+ }
+
+ if (desc->type == NSCD_CFG_DATA_STRING) {
+ if (strcmp(str, NSCD_NULL) == 0)
+ *(char **)data_p = NULL;
+ else {
+ /* remove the " char if quoted string */
+ if (str[0] == '"') {
+ c = str + strlen(str) - 1;
+ if (*c == '"')
+ *c = '\0';
+ *(char **)data_p = str + 1;
+ } else
+ *(char **)data_p = str;
+
+ }
+ return (NSCD_SUCCESS);
+ }
+
+ if (str == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("data must be specified for %s"), desc->id.name);
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
+ msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s\n", msg);
+
+ return (NSCD_INVALID_ARGUMENT);
+
+ }
+
+ switch (desc->type) {
+
+ case NSCD_CFG_DATA_BOOLEAN:
+
+ if (strcasecmp(str, "yes") == 0)
+ *(nscd_bool_t *)data = nscd_true;
+ else if (strcasecmp(str, "no") == 0)
+ *(nscd_bool_t *)data = nscd_false;
+ else {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("data (%s) must be 'yes' or 'no' for %s"),
+ str, desc->id.name);
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
+ msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s\n", msg);
+
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ break;
+
+ case NSCD_CFG_DATA_INTEGER:
+
+ errno = 0;
+ *(int *)data = (int)strtol(str, (char **)NULL, 10);
+ if (errno != NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("unable to convert data (%s) for %s"),
+ str, desc->id.name);
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s\n", msg);
+
+ return (rc);
+ }
+
+ break;
+
+ case NSCD_CFG_DATA_BITMAP:
+
+ errno = 0;
+ bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10);
+ if (errno != NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("unable to convert data (%s) for %s"),
+ str, desc->id.name);
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s\n", msg);
+
+ return (rc);
+ }
+
+ _nscd_cfg_bitmap_set(data, bitmap);
+
+ break;
+
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+
+nscd_rc_t
+_nscd_cfg_set(
+ nscd_cfg_handle_t *handle,
+ void *data,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_set";
+ int dlen;
+ nscd_cfg_id_t *nswdb;
+ nscd_cfg_param_desc_t *desc, *gdesc;
+ nscd_cfg_group_info_t *gi;
+ char *nswdb_name, *param_name;
+ void *pdata = NULL;
+ void *cfg_data, *vdata_addr = NULL;
+ nscd_bool_t get_group = 0;
+ nscd_bool_t in = nscd_true;
+ nscd_cfg_lock_t *lock = NULL;
+ nscd_rc_t rc = NSCD_SUCCESS;
+
+ if (handle == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "handle is NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ nswdb = handle->nswdb;
+ desc = (nscd_cfg_param_desc_t *)handle->desc;
+ if (nswdb == NULL)
+ nswdb_name = "global";
+ else
+ nswdb_name = nswdb->name;
+ param_name = desc->id.name;
+
+ if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_VLEN_DATA)) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "data == NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) ||
+ _nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
+ get_group = nscd_true;
+
+ /*
+ * locate the current value of the param or group
+ * and lock the config data for writing
+ */
+ rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc,
+ nswdb, get_group, &vdata_addr, &dlen, &lock);
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to locate config data (rc = %d)\n", rc);
+ return (rc);
+ }
+
+ if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) &&
+ ((nscd_cfg_group_info_t *)cfg_data)->num_param !=
+ ((nscd_cfg_group_info_t *)data)->num_param) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "number of parameters in group <%s : %s> not equal: "
+ "%d in input data, should be %d\n",
+ NSCD_STR_OR_GLOBAL(nswdb_name),
+ NSCD_STR_OR_NULL(param_name),
+ ((nscd_cfg_group_info_t *)data)->num_param,
+ ((nscd_cfg_group_info_t *)cfg_data)->num_param);
+
+ rc = NSCD_INVALID_ARGUMENT;
+ goto error_exit;
+ }
+
+ /*
+ * if variable length data, we want the address
+ * of the pointer pointing to the data
+ */
+ if (vdata_addr != NULL)
+ cfg_data = vdata_addr;
+
+ /*
+ * just copy in the specified data, if no need
+ * to verify the data or notify the associated
+ * component
+ */
+ if (get_group == nscd_true) {
+
+ gdesc = &_nscd_cfg_param_desc[desc->g_index];
+
+ rc = _nscd_cfg_copy_group_data_merge(
+ gdesc, &pdata, data, cfg_data,
+ desc->id.index, data);
+
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to copy group data <%s : %s>\n",
+ NSCD_STR_OR_GLOBAL(nswdb_name),
+ NSCD_STR_OR_NULL(param_name));
+
+ goto error_exit;
+ }
+
+ rc = _nscd_cfg_notify_s(gdesc, nswdb,
+ pdata, errorp);
+
+ } else
+ rc = _nscd_cfg_notify_s(desc, nswdb, data,
+ errorp);
+
+ if (rc != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "verifying/notifying of new configuration "
+ "parameter <%s : %s> failed. %s\n",
+ NSCD_STR_OR_GLOBAL(nswdb_name),
+ param_name, (*errorp && (*errorp)->msg) ?
+ (*errorp)->msg : "");
+
+ goto error_exit;
+ }
+
+ /*
+ * Move the new config into the config store
+ */
+ rc = NSCD_CFG_SET_PARAM_FAILED;
+ if (_nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_GROUP)) {
+ gi = _nscd_cfg_get_gi(pdata);
+ rc = _nscd_cfg_copy_group_data_in(gdesc, gi,
+ cfg_data, pdata);
+ } else {
+ /*
+ * nscd_true asks _nscd_cfg_copy_param_data to
+ * set addr of the vlen data in 'cfg_data' rather
+ * than copying the data content
+ */
+ if (pdata != NULL)
+ _nscd_cfg_free_vlen_data_group(gdesc,
+ pdata, in);
+
+ rc = _nscd_cfg_copy_param_data(desc,
+ cfg_data, data, in, nscd_true);
+ }
+
+ if (rc != NSCD_SUCCESS) {
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to make new param data <%s : %s> current\n",
+ NSCD_STR_OR_GLOBAL(nswdb_name),
+ NSCD_STR_OR_NULL(param_name));
+ }
+
+ error_exit:
+
+ _nscd_cfg_unlock(lock);
+
+ return (rc);
+}
+
+nscd_rc_t
+_nscd_cfg_set_linked(
+ nscd_cfg_handle_t *handle,
+ void *data,
+ nscd_cfg_error_t **errorp)
+{
+ char *me = "_nscd_cfg_set_linked";
+ nscd_cfg_id_t *nswdb;
+ nscd_cfg_handle_t *hl;
+ nscd_cfg_param_desc_t *desc;
+ char *nswdb_name, *param_name, *dbl;
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_cfg_nsw_spc_default_t *spc;
+ int i;
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+
+ if (handle == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "handle is NULL\n");
+ return (NSCD_INVALID_ARGUMENT);
+ }
+
+ nswdb = handle->nswdb;
+ desc = (nscd_cfg_param_desc_t *)handle->desc;
+
+ /*
+ * no need to do the special linking thing,
+ * if a global param, or a group, or not a linked param
+ */
+ if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag,
+ NSCD_CFG_PFLAG_GROUP) ||
+ _nscd_cfg_flag_is_not_set(desc->pflag,
+ NSCD_CFG_PFLAG_LINKED))
+ return (_nscd_cfg_set(handle, data, errorp));
+ else
+ nswdb_name = nswdb->name;
+ param_name = desc->id.name;
+
+ /*
+ * if a param is linked to another, it can not be
+ * changed directly
+ */
+ for (i = 0; i < _nscd_cfg_num_link_default; i++) {
+
+ if (_nscd_cfg_nsw_link_default[i].data == NULL)
+ continue;
+
+ if (strcmp(_nscd_cfg_nsw_link_default[i].db,
+ nswdb_name) == 0 &&
+ _nscd_cfg_nsw_link_default[i].group_off ==
+ desc->g_offset &&
+ _nscd_cfg_nsw_link_default[i].param_off ==
+ desc->p_offset) {
+
+ rc = NSCD_CFG_READ_ONLY;
+
+ (void) snprintf(msg, sizeof (msg),
+gettext("vaule of \'%s\' not changeable, change that of \'%s\' instead"),
+ nswdb->name, "passwd");
+
+ if (errorp != NULL)
+ *errorp = _nscd_cfg_make_error(rc, msg);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "ERROR: %s\n", msg);
+
+ return (rc);
+ }
+ }
+
+ /*
+ * if a param is linked from another, it should be verify
+ * and changed first
+ */
+ for (i = 0; i < _nscd_cfg_num_link_default; i++) {
+
+ if (_nscd_cfg_nsw_link_default[i].data == NULL)
+ continue;
+
+ spc = _nscd_cfg_nsw_link_default[i].data;
+
+ if (strcmp(spc->db, nswdb_name) == 0 &&
+ spc->group_off == desc->g_offset &&
+ spc->param_off == desc->p_offset) {
+
+ rc = _nscd_cfg_set(handle, data, errorp);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ break;
+ }
+ }
+
+ /*
+ * then change all those linked to the one that has been changed
+ */
+ for (i = 0; i < _nscd_cfg_num_link_default; i++) {
+
+ if (_nscd_cfg_nsw_link_default[i].data == NULL)
+ continue;
+
+ spc = _nscd_cfg_nsw_link_default[i].data;
+
+ if (strcmp(spc->db, nswdb_name) == 0 &&
+ spc->group_off == desc->g_offset &&
+ spc->param_off == desc->p_offset &&
+ _nscd_cfg_nsw_link_default[i].group_off ==
+ desc->g_offset &&
+ _nscd_cfg_nsw_link_default[i].param_off ==
+ desc->p_offset) {
+
+ dbl = _nscd_cfg_nsw_link_default[i].db;
+
+ rc = _nscd_cfg_get_handle(param_name, dbl,
+ &hl, errorp);
+ rc = _nscd_cfg_set(hl, data, errorp);
+ _nscd_cfg_free_handle(hl);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ }
+ }
+
+ return (_nscd_cfg_set(handle, data, errorp));
+}
+
+/*
+ * Return a list of space-separated database names that
+ * have at least one of the input sources appeared in the
+ * configured nsswitch policy string of the databases.
+ * The return string should be freed by the caller.
+ *
+ * For compat sources (compat_group and compat_passwd),
+ * "group" will be returned, if the policy string for
+ * compat_group contains one of the input sources. Same
+ * for compat_passwd and passwd.
+ */
+char *
+_nscd_srcs_in_db_nsw_policy(
+ int num_src,
+ char **srcs)
+{
+ uint8_t i, j, n = 0, nc = 0;
+ uint8_t compat_grp = 0, compat_pwd = 0;
+ uint8_t *db;
+ uint8_t *db_compat;
+ int dlen = 0;
+ nscd_cfg_nsw_db_data_t *dbcfg;
+ nscd_cfg_switch_t *sw;
+ char *outstr = NULL;
+ char *dbname;
+
+ db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t));
+ if (db == NULL)
+ return (NULL);
+
+ db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db,
+ sizeof (uint8_t));
+ if (db_compat == NULL) {
+ free(db);
+ return (NULL);
+ }
+
+ for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
+
+ (void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]);
+
+ dbcfg = &nscd_cfg_nsw_db_data_current[i];
+ sw = &dbcfg->sw;
+ if (sw->nsw_config_string == NULL)
+ continue;
+
+ dbname = _nscd_cfg_nsw_db[i].name;
+ for (j = 0; j < num_src; j++) {
+ if (strstr(sw->nsw_config_string, srcs[j]) !=
+ NULL) {
+ db[n++] = i;
+ dlen += strlen(dbname) + 1;
+ } else if (strcmp(sw->nsw_config_string,
+ "compat") == 0) {
+ if (strcmp(dbname, "passwd") == 0) {
+ compat_pwd = 1;
+ dlen += 7;
+ } else if (strcmp(dbname, "group") == 0) {
+ compat_grp = 1;
+ dlen += 6;
+ } else {
+ db_compat[nc++] = i;
+ dlen += strlen(dbname) + 1;
+
+ }
+ }
+ }
+ (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
+ }
+
+ if (dlen != NULL)
+ outstr = (char *)calloc(1, dlen);
+ if (outstr == NULL) {
+ free(db_compat);
+ free(db);
+ return (NULL);
+ }
+
+ for (j = 0; j < n; j++) {
+ dbname = _nscd_cfg_nsw_db[db[j]].name;
+ if (strstr(dbname, "group_compat") != NULL) {
+ if (compat_grp == 1)
+ dbname = "group";
+ else
+ continue;
+ } else if (strstr(dbname, "passwd_compat") != NULL) {
+ if (compat_pwd == 1)
+ dbname = "passwd";
+ else
+ continue;
+ }
+
+ (void) strlcat(outstr, dbname, dlen);
+ (void) strlcat(outstr, ",", dlen);
+ }
+
+ for (j = 0; j < nc; j++) {
+ dbname = _nscd_cfg_nsw_db[db_compat[j]].name;
+ if (compat_pwd == 1) {
+ (void) strlcat(outstr, dbname, dlen);
+ (void) strlcat(outstr, " ", dlen);
+ }
+ }
+
+ free(db);
+ free(db_compat);
+ return (outstr);
+
+}
diff --git a/usr/src/cmd/nscd/nscd_config.h b/usr/src/cmd/nscd/nscd_config.h
new file mode 100644
index 0000000000..44b3c9489f
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_config.h
@@ -0,0 +1,653 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_CONFIG_H
+#define _NSCD_CONFIG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include "nscd_common.h"
+
+/*
+ * nscd_cfg_id_t is used to identify a config/stat
+ * object. 'index' provides a way to quickly locate
+ * the object in the associated configuration list.
+ * 'name' can be looked up in the config info database
+ * to obtain the index.
+ */
+typedef struct {
+ int index;
+ char *name;
+} nscd_cfg_id_t;
+
+/*
+ * forward declaration of nscd_cfg_param_desc_t
+ */
+struct nscd_cfg_param_desc;
+
+/*
+ * for operations that apply to configuration data
+ * in all the nsswitch databases
+ */
+#define NSCD_CFG_NSW_ALLDB "ALLDB"
+#define NSCD_CFG_NSW_ALLDB_INDEX 9999
+
+/*
+ * configuration lists includes switch databases (eg. hosts, passwd),
+ * switch sources (eg. files, ldap), config parameter descriptions
+ * (defined below), and status/statistic counter descriptions (defined
+ * below)
+ */
+typedef struct {
+ int num;
+ nscd_cfg_id_t **list;
+} nscd_cfg_list_t;
+
+/*
+ * type of configuration list
+ */
+typedef enum {
+ NSCD_CFG_LIST_NSW_DB = 0,
+ NSCD_CFG_LIST_NSW_SRC = 1,
+ NSCD_CFG_LIST_PARAM = 2,
+ NSCD_CFG_LIST_STAT = 3
+} nscd_cfg_list_type_t;
+
+/*
+ * A config handle identifies config or stat data,
+ * which if is nsswitch database specific, 'nswdb'
+ * indicates the id of the database; if global,
+ * 'nswdb' should be null. 'desc' is the config
+ * param or stat description assocaited with the
+ * data.
+ */
+typedef struct {
+ nscd_cfg_id_t *nswdb;
+ void *desc;
+ nscd_cfg_list_type_t type;
+} nscd_cfg_handle_t;
+
+/*
+ * type of configuration/statistics data
+ */
+typedef enum {
+ NSCD_CFG_DATA_NONE = 0,
+ NSCD_CFG_DATA_INTEGER = 1,
+ NSCD_CFG_DATA_BOOLEAN = 2,
+ NSCD_CFG_DATA_STRING = 3,
+ NSCD_CFG_DATA_BITMAP = 4,
+ NSCD_CFG_DATA_PERCENT = 5
+} nscd_cfg_data_type_t;
+#define NSCD_CFG_NUM_DATA_TYPE 5
+
+/*
+ * data flag is attached to config/stat data passed between
+ * function to specify the nature/type of action to perform
+ */
+
+#define NSCD_CFG_DFLAG_NONE 0x0000
+
+/*
+ * data should not be freed by receiver;
+ * otherwise it should be freed
+ */
+#define NSCD_CFG_DFLAG_STATIC_DATA 0x0001
+
+/*
+ * data is sent/received due to nscd initialization;
+ * otherwise due to modification of the config data
+ * requested by users
+ */
+#define NSCD_CFG_DFLAG_INIT 0x0002
+
+/*
+ * the entire group of data is, or should be, sent;
+ * otherwise only a single parameter/stat value
+ */
+#define NSCD_CFG_DFLAG_GROUP 0x0004
+
+/*
+ * the data sent/received is to be verified by the
+ * 'verify' function defined in the parameter
+ * description
+ */
+#define NSCD_CFG_DFLAG_VERIFY 0x0008
+
+/*
+ * the data sent/received is to be processed by the
+ * 'notify' function defined in the parameter
+ * description
+ */
+#define NSCD_CFG_DFLAG_NOTIFY 0x0010
+
+/*
+ * the data sent/received is to be applied to all
+ * nsswitch databases
+ */
+#define NSCD_CFG_DFLAG_SET_ALL_DB 0x0020
+
+/*
+ * the entire group of data is sent/received;
+ * however, only those parameters selected by
+ * the bitmap in the group info should be
+ * processed
+ */
+#define NSCD_CFG_DFLAG_BIT_SELECTED 0x0040
+
+/*
+ * param flag is defined in the parameter description.
+ * It specifies what operation should be applied to, or
+ * the nature of, the config parameters.
+ */
+
+#define NSCD_CFG_PFLAG_NONE 0x0000
+
+/*
+ * At init/refresh time, send the parameter value
+ * with the data of the entire group; otherwise
+ * send the parameter value only
+ */
+#define NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP 0x0001
+
+/*
+ * At user requested update time, send the parameter
+ * value with the data of the entire group; otherwise
+ * send the parameter value only
+ */
+#define NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP 0x0002
+
+/*
+ * At init/refresh time, send the config data
+ * once for each nsswitch database
+ */
+#define NSCD_CFG_PFLAG_INIT_SET_ALL_DB 0x0004
+
+/*
+ * At user requested update time, send the per nsswitch
+ * database (non-global) data just one time (not once
+ * for each nsswitch database)
+ */
+#define NSCD_CFG_PFLAG_UPDATE_SEND_NON_GLOBAL_ONCE 0x0008
+
+/*
+ * send entire group data, but use bitmap to indicate
+ * the one config parameter being processed. This flag
+ * can only be sepcified for a group description
+ */
+#define NSCD_CFG_PFLAG_SEND_BIT_SELECTED 0x0010
+
+/*
+ * data is global, not per nsswitch database
+ */
+#define NSCD_CFG_PFLAG_GLOBAL 0x0020
+
+/*
+ * data is group data, not individual parameter value
+ */
+#define NSCD_CFG_PFLAG_GROUP 0x0040
+
+/*
+ * data is of variable length
+ */
+#define NSCD_CFG_PFLAG_VLEN_DATA 0x0080
+
+/*
+ * data is hidden, for internal use only, get/set not allowed
+ */
+#define NSCD_CFG_PFLAG_HIDDEN 0x0100
+
+/*
+ * data is linked, using the value of a different database
+ */
+#define NSCD_CFG_PFLAG_LINKED 0x0200
+
+/*
+ * data is obsolete, ignored with warning, should not be displayed
+ */
+#define NSCD_CFG_PFLAG_OBSOLETE 0x0400
+
+/*
+ * structure for error reporting
+ */
+typedef struct {
+ nscd_rc_t rc;
+ char *msg;
+} nscd_cfg_error_t;
+
+/*
+ * typedef for flag, bitmap, and boolean
+ */
+typedef int nscd_cfg_flag_t;
+typedef int nscd_cfg_bitmap_t;
+
+/*
+ * struct nscd_cfg_param_desc is used to describe each and
+ * every one of the nscd config parameters so that they can
+ * be processed generically by the configuration management
+ * component. During init or update time, config data needs
+ * to be pushed to other nscd components (frontend, switch
+ * engine, cache backend, and so on) for further processing.
+ * The 'verify' and 'notify' functions are the hooks provided
+ * by these other components to validate and store the new
+ * config data. The 'p_check' field, if specified, points
+ * to a set of data used for preliminary check of a parameter
+ * value (range, length, null checking etc).
+ */
+typedef struct nscd_cfg_param_desc {
+ nscd_cfg_id_t id;
+ nscd_cfg_data_type_t type;
+ nscd_cfg_flag_t pflag;
+ int p_size;
+ size_t p_offset;
+ int p_fn;
+ int g_size;
+ size_t g_offset;
+ int g_index;
+ void *p_check;
+ char *nfunc_name;
+ char *vfunc_name;
+ nscd_rc_t (*notify)(void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void *cookie);
+ nscd_rc_t (*verify)(void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie);
+} nscd_cfg_param_desc_t;
+
+/*
+ * the _nscd_cfg_get_param_desc_list function returns
+ * the list of nscd config param descriptions at
+ * run time
+ */
+typedef struct {
+ int num;
+ nscd_cfg_param_desc_t **list;
+} nscd_cfg_param_desc_list_t;
+
+/* this describes data of variable length */
+typedef struct {
+ void *ptr;
+ int len;
+} nscd_cfg_vlen_data_t;
+
+/*
+ * The following defines the various global and nsswitch
+ * database specific data structures for all the groups of
+ * configuration parameters. Before each one, there lists
+ * the associated group info which contains the number of
+ * parameters and the corresponding bitmap.
+ */
+
+typedef struct {
+ int num_param;
+ nscd_cfg_bitmap_t bitmap;
+} nscd_cfg_group_info_t;
+#define NSCD_CFG_GROUP_INFO_NULL {-1, 0x0000}
+
+/*
+ * frontend param group (Per nsswitch database)
+ */
+#define NSCD_CFG_GROUP_INFO_FRONTEND {1, 0x0001}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ int worker_thread_per_nsw_db;
+} nscd_cfg_frontend_t;
+
+/*
+ * switch engine param group (Per nsswitch database)
+ */
+#define NSCD_CFG_GROUP_INFO_SWITCH {7, 0x07f}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ char *nsw_config_string;
+ char *nsw_config_db;
+ nscd_bool_t enable_lookup;
+ nscd_bool_t enable_loopback_checking;
+ int max_nsw_state_per_db;
+ int max_nsw_state_per_thread;
+ int max_getent_ctx_per_db;
+} nscd_cfg_switch_t;
+
+/*
+ * log/debug param group (global)
+ */
+#define NSCD_CFG_GROUP_INFO_GLOBAL_LOG {3, 0x0007}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ char *logfile;
+ int debug_level;
+ int debug_comp;
+} nscd_cfg_global_log_t;
+
+/*
+ * frontend param group (global)
+ */
+#define NSCD_CFG_GROUP_INFO_GLOBAL_FRONTEND {2, 0x0003}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ int common_worker_threads;
+ int cache_hit_threads;
+} nscd_cfg_global_frontend_t;
+
+/*
+ * self credential param group (global)
+ */
+#define NSCD_CFG_GROUP_INFO_GLOBAL_SELFCRED {3, 0x0007}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ nscd_bool_t enable_selfcred;
+ int max_per_user_nscd;
+ int per_user_nscd_ttl;
+} nscd_cfg_global_selfcred_t;
+
+/*
+ * switch engine param group (global)
+ */
+#define NSCD_CFG_GROUP_INFO_GLOBAL_SWITCH {3, 0x0007}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ nscd_bool_t enable_lookup_g;
+ nscd_bool_t enable_loopback_checking_g;
+ int check_smf_state_interval_g;
+} nscd_cfg_global_switch_t;
+
+/*
+ * nscd_cfg_param_desc_t should always have nscd_cfg_id_t
+ * as its first field. _nscd_cfg_get_desc below provides
+ * an way to get to the nscd_cfg_param_desc_t from a
+ * pointer to the static nscd_cfg_id_t returned by the
+ * various_nscd_cfg_* functions
+ */
+#define _nscd_cfg_get_desc_i(id) ((nscd_cfg_param_desc_t *)(id))
+
+#define _nscd_cfg_get_desc(h) ((h)->desc)
+
+/*
+ * The various param group structure should always have
+ * nscd_cfg_group_info_t as its first field.
+ * _nscd_cfg_get_gi below provides a generic way to
+ * get to the nscd_cfg_group_info_t from a void pointer
+ * to the various param group structure returned by the
+ * _nscd_cfg_* functions
+ */
+#define _nscd_cfg_get_gi(voidp) ((nscd_cfg_group_info_t *)(voidp))
+
+/*
+ * It is possible in the future, we will need more bits
+ * than those in nscd_cfg_flag_t and nscd_cfg_bitmap_t. To
+ * make it easier to extend, the following macro should be
+ * used to deal with flags and bitmaps.
+ * m, m1, m2, ma: mask, n: nth bit (0 based)
+ * f: flag, v: value
+ */
+#define NSCD_CFG_BITMAP_ZERO 0
+#define _nscd_cfg_bitmap_is_set(m, n) (((m) >> n) & 1)
+#define _nscd_cfg_bitmap_is_not_set(m, n) (!(((m) >> n) & 1))
+#define _nscd_cfg_bitmap_is_equal(m1, m2) ((m1) == (m2))
+#define _nscd_cfg_bitmap_value(m) (m)
+#define _nscd_cfg_bitmap_set_nth(m, n) ((m) |= (1 << n))
+#define _nscd_cfg_bitmap_set(ma, m) (*(nscd_cfg_bitmap_t *) \
+ (ma) = (m))
+#define _nscd_cfg_bitmap_valid(m1, m2) (((m1) & ~(m2)) == 0)
+
+#define NSCD_CFG_FLAG_ZERO 0
+#define _nscd_cfg_flag_is_set(f, v) ((f) & (v))
+#define _nscd_cfg_flag_is_not_set(f, v) (!((f) & (v)))
+#define _nscd_cfg_flag_value(f) (f)
+#define _nscd_cfg_flag_set(f, v) ((f) | (v))
+#define _nscd_cfg_flag_unset(f, v) ((f) & ~(v))
+
+/*
+ * handy macros
+ */
+#define NSCD_NULL "NULL"
+#define NSCD_CFG_MAX_ERR_MSG_LEN 1024
+#define NSCD_STR_OR_NULL(s) ((s) == NULL ? "NULL" : (s))
+#define NSCD_STR_OR_GLOBAL(s) ((s) == NULL ? "GLOBAL" : (s))
+#define NSCD_Y_OR_N(s) (*(nscd_bool_t *)s == nscd_true ? \
+ "yes" : "no")
+
+#define NSCD_ERR2MSG(e) (((e) && (e)->msg) ? (e)->msg : "")
+
+
+/*
+ * This macro is based on offsetof defined in stddef_iso.h,
+ * it gives the size of 'm' in structure 's' without needing
+ * the declaration of a 's' variable (as macro sizeof does)
+ */
+#define NSCD_SIZEOF(s, m) (sizeof (((s *)0)->m))
+
+
+/*
+ * struct nscd_cfg_stat_desc is used to describe each and every
+ * one of the nscd statistics counters so that they can be
+ * processed generically by the configuration management
+ * component. The component does not keep a separate copy of
+ * all counters, which should be maintained by other nscd
+ * components. The 'get_stat' functions defined in the
+ * stat description are supplied by those components and used
+ * by the config management component to request and print
+ * counters on behave of the users. The free_stat function
+ * returned by those components will also be used to free
+ * the stat data if the NSCD_CFG_DFLAG_STATIC_DATA bit is
+ * not set in dflag.
+ */
+typedef struct nscd_cfg_stat_desc {
+ nscd_cfg_id_t id;
+ nscd_cfg_data_type_t type;
+ nscd_cfg_flag_t sflag;
+ nscd_cfg_group_info_t gi;
+ int s_size;
+ size_t s_offset;
+ int s_fn;
+ int g_size;
+ size_t g_offset;
+ int g_index;
+ char *gsfunc_name;
+ nscd_rc_t (*get_stat)(void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)
+ (void *stat),
+ nscd_cfg_error_t **errorp);
+} nscd_cfg_stat_desc_t;
+
+/*
+ * stat flag is defined in the stat description. It
+ * specifies the nature of the statistics counters.
+ */
+
+#define NSCD_CFG_SFLAG_NONE 0x0000
+
+/*
+ * statistics counter is global, not per nsswitch database
+ */
+#define NSCD_CFG_SFLAG_GLOBAL 0x0001
+
+/*
+ * description is for counter group, not individual counter
+ */
+#define NSCD_CFG_SFLAG_GROUP 0x0002
+
+/*
+ * The following defines the various global and nsswitch
+ * database specific data structures for all the groups of
+ * statistics counters. Before each one, there lists
+ * the associated group info which contains the number of
+ * counters and the corresponding bitmap.
+ */
+
+/*
+ * switch engine stat group (Per nsswitch database)
+ */
+#define NSCD_CFG_STAT_GROUP_INFO_SWITCH {6, 0x003f}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ int lookup_request_received;
+ int lookup_request_queued;
+ int lookup_request_in_progress;
+ int lookup_request_succeeded;
+ int lookup_request_failed;
+ int loopback_nsw_db_skipped;
+} nscd_cfg_stat_switch_t;
+
+/*
+ * log/debug stat group (global)
+ */
+#define NSCD_CFG_STAT_GROUP_INFO_GLOBAL_LOG {1, 0x0001}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ int entries_logged;
+} nscd_cfg_stat_global_log_t;
+
+/*
+ * switch engine stat group (global)
+ */
+#define NSCD_CFG_STAT_GROUP_INFO_GLOBAL_SWITCH {6, 0x003f}
+typedef struct {
+ nscd_cfg_group_info_t gi;
+ int lookup_request_received_g;
+ int lookup_request_queued_g;
+ int lookup_request_in_progress_g;
+ int lookup_request_succeeded_g;
+ int lookup_request_failed_g;
+ int loopback_nsw_db_skipped_g;
+} nscd_cfg_stat_global_switch_t;
+
+/*
+ * control structure for appending string data to a buffer
+ */
+typedef struct {
+ char *buf;
+ char *next;
+ int size;
+ int used;
+ int left;
+ int real;
+} nscd_cfg_buf_t;
+
+/*
+ * internal configuration management related functions
+ */
+nscd_rc_t _nscd_cfg_init();
+
+nscd_rc_t
+_nscd_cfg_get_param_desc_list(
+ nscd_cfg_param_desc_list_t **list);
+
+nscd_rc_t
+_nscd_cfg_get_handle(
+ char *param_name,
+ char *nswdb_name,
+ nscd_cfg_handle_t **handle,
+ nscd_cfg_error_t **errorp);
+
+nscd_cfg_error_t *
+_nscd_cfg_make_error(
+ nscd_rc_t rc,
+ char *msg);
+
+void
+_nscd_cfg_free_handle(
+ nscd_cfg_handle_t *handle);
+
+void
+_nscd_cfg_free_group_data(
+ nscd_cfg_handle_t *handle,
+ void *data);
+
+void
+_nscd_cfg_free_param_data(
+ void *data);
+
+void
+_nscd_cfg_free_error(
+ nscd_cfg_error_t *error);
+
+nscd_rc_t
+_nscd_cfg_get(
+ nscd_cfg_handle_t *handle,
+ void **data,
+ int *data_len,
+ nscd_cfg_error_t **errorp);
+
+nscd_rc_t
+_nscd_cfg_set(
+ nscd_cfg_handle_t *handle,
+ void *data,
+ nscd_cfg_error_t **errorp);
+
+nscd_rc_t
+_nscd_cfg_str_to_data(
+ nscd_cfg_param_desc_t *desc,
+ char *str,
+ void *data,
+ void **data_p,
+ nscd_cfg_error_t **errorp);
+
+nscd_rc_t
+_nscd_cfg_prelim_check(
+ nscd_cfg_param_desc_t *desc,
+ void *data,
+ nscd_cfg_error_t **errorp);
+
+nscd_rc_t
+_nscd_cfg_read_file(
+ char *filename,
+ nscd_cfg_error_t **errorp);
+
+nscd_rc_t
+_nscd_cfg_set_linked(
+ nscd_cfg_handle_t *handle,
+ void *data,
+ nscd_cfg_error_t **errorp);
+
+char *
+_nscd_srcs_in_db_nsw_policy(
+ int num_src,
+ char **srcs);
+
+nscd_rc_t
+_nscd_cfg_read_nsswitch_file(
+ char *filename,
+ nscd_cfg_error_t **errorp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_CONFIG_H */
diff --git a/usr/src/cmd/nscd/nscd_db.h b/usr/src/cmd/nscd/nscd_db.h
new file mode 100644
index 0000000000..7186f0d0dd
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_db.h
@@ -0,0 +1,253 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_DB_H
+#define _NSCD_DB_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nss_dbdefs.h> /* nssuint_t */
+#include "nscd_common.h"
+
+/* make a pointer 8-byte aligned, or an integer a multiple of 8 */
+#define roundup(x) (((unsigned long)(x)+7) & ~7)
+
+/*
+ * type of nscd data
+ */
+#define NSCD_DATA_UNKNOWN 0
+#define NSCD_DATA_NSW_CONFIG 1
+#define NSCD_DATA_NSW_STATE_BASE 2
+#define NSCD_DATA_GETENT_CTX_BASE 3
+#define NSCD_DATA_BACKEND_INFO 4
+#define NSCD_DATA_BACKEND_INFO_DB 5
+#define NSCD_DATA_CFG_NSW_DB_INDEX 6
+#define NSCD_DATA_CFG_NSW_SRC_INDEX 7
+#define NSCD_DATA_CFG_PARAM_INDEX 8
+#define NSCD_DATA_CFG_STAT_INDEX 9
+#define NSCD_DATA_ADDR 127
+#define NSCD_DATA_CTX_ADDR 128
+
+/*
+ * database operation options
+ */
+typedef enum {
+ NSCD_GET_FIRST_DB_ENTRY = 1,
+ NSCD_GET_NEXT_DB_ENTRY = 2,
+ NSCD_GET_EXACT_DB_ENTRY = 3,
+ NSCD_ADD_DB_ENTRY_FIRST = 4,
+ NSCD_ADD_DB_ENTRY_LAST = 5,
+ NSCD_ADD_DB_ENTRY_REPLACE = 6,
+ NSCD_ADD_DB_ENTRY_IF_NONE = 7,
+ NSCD_DEL_FIRST_DB_ENTRY = 8,
+ NSCD_DEL_ALL_DB_ENTRY = 9,
+ NSCD_DEL_EXACT_DB_ENTRY = 10
+} nscd_db_option_t;
+
+/*
+ * This structure defines an instance of the
+ * nscd database entry.
+ */
+typedef struct nscd_db_entry {
+ int type;
+ int id_num;
+ int num_data;
+ int num_array;
+ char *name;
+ void **data_array;
+} nscd_db_entry_t;
+
+/*
+ * sequence number attached to nscd data
+ */
+typedef nssuint_t nscd_seq_num_t;
+typedef nssuint_t nscd_cookie_t;
+
+/*
+ * The nscd_access_s datatype represents a nscd
+ * access data structure. It is an opaque structure.
+ */
+struct nscd_access_s;
+typedef struct nscd_access_s nscd_access_t;
+struct nscd_acc_data_s;
+typedef struct nscd_acc_data_s nscd_acc_data_t;
+
+/*
+ * The nscd_db_t datatype represents a nscd
+ * database. It is also an opaque structure.
+ */
+struct nscd_db_s;
+typedef struct nscd_db_s nscd_db_t;
+
+/*
+ * four sizes for a nscd database:
+ * large, medium, small, tiny
+ */
+#define NSCD_DB_SIZE_LARGE 1
+#define NSCD_DB_SIZE_MEDIUM 2
+#define NSCD_DB_SIZE_SMALL 3
+#define NSCD_DB_SIZE_TINY 4
+
+/*
+ * options for _nscd_alloc()
+ */
+#define NSCD_ALLOC_MUTEX 0x0001
+#define NSCD_ALLOC_RWLOCK 0x0002
+#define NSCD_ALLOC_COND 0x0004
+
+/*
+ * prototypes
+ */
+nscd_seq_num_t
+_nscd_get_seq_num();
+
+nscd_cookie_t
+_nscd_get_cookie();
+
+nscd_acc_data_t *
+_nscd_get(
+ nscd_acc_data_t *data);
+
+nscd_acc_data_t
+*_nscd_set(
+ nscd_acc_data_t *old,
+ nscd_acc_data_t *new);
+
+void
+_nscd_release(
+ nscd_acc_data_t *data);
+
+nscd_acc_data_t
+*_nscd_rdlock(
+ nscd_acc_data_t *data);
+
+nscd_acc_data_t
+*_nscd_wrlock(
+ nscd_acc_data_t *data);
+
+void
+_nscd_rw_unlock(
+ nscd_acc_data_t *data);
+
+void
+_nscd_rw_unlock_no_release(
+ nscd_acc_data_t *data);
+
+nscd_acc_data_t
+*_nscd_mutex_lock(
+ nscd_acc_data_t *data);
+
+void
+_nscd_mutex_unlock(
+ nscd_acc_data_t *data);
+
+void
+_nscd_cond_signal(
+ nscd_acc_data_t *data);
+
+void
+_nscd_cond_wait(
+ nscd_acc_data_t *data,
+ cond_t *cond);
+
+nscd_acc_data_t *
+_nscd_alloc(
+ int type,
+ size_t size,
+ void (*data_free)(
+ nscd_acc_data_t *data),
+ int option);
+
+nscd_rc_t
+_nscd_add_int_addr(
+ void *ptr,
+ int type,
+ nscd_seq_num_t seq_num);
+
+rwlock_t *
+_nscd_is_int_addr(
+ void *ptr,
+ nscd_seq_num_t seq_num);
+
+void
+_nscd_del_int_addr(
+ void *ptr,
+ nscd_seq_num_t seq_num);
+
+nscd_db_t *
+_nscd_alloc_db(
+ int size);
+
+void
+_nscd_free_db(
+ nscd_db_t *db);
+
+nscd_db_entry_t *
+_nscd_alloc_db_entry(
+ int type,
+ const char *name,
+ int dataSize,
+ int num_data,
+ int num_array);
+
+const nscd_db_entry_t *
+_nscd_get_db_entry(
+ const nscd_db_t *db,
+ int type,
+ const char *str,
+ nscd_db_option_t option,
+ int id_num);
+
+nscd_rc_t
+_nscd_add_db_entry(
+ nscd_db_t *db,
+ const char *str,
+ nscd_db_entry_t *entry,
+ nscd_db_option_t option);
+
+nscd_rc_t
+_nscd_delete_db_entry(
+ nscd_db_t *db,
+ int type,
+ const char *str,
+ nscd_db_option_t option,
+ int id_num);
+
+
+void *
+_nscd_create_int_addrDB();
+
+void
+_nscd_destroy_int_addrDB();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_DB_H */
diff --git a/usr/src/cmd/nscd/nscd_dbimpl.c b/usr/src/cmd/nscd/nscd_dbimpl.c
new file mode 100644
index 0000000000..822b4b6aba
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_dbimpl.c
@@ -0,0 +1,617 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "nscd_db.h"
+
+/*
+ * This file implements the database functionality used by the
+ * switch and configuration components. The implementation is
+ * based on hash and has table. If the need arises in the future,
+ * the code in this file can be changed to use other algorithms.
+ * The following lists the functions implemented:
+ *
+ * _nscd_add_db_entry
+ * _nscd_delete_db_entry
+ * _nscd_get_db_entry
+ * _nscd_alloc_db
+ * _nscd_free_db
+ * _nscd_walk_db
+ * _nscd_delete_db_entry_cookie
+ */
+
+/*
+ * This structure defines an instance of the hash entry
+ * which implements the nscd database entry. The
+ * db_entry field should always be the first one in
+ * the structure.
+ */
+typedef struct nscd_hash {
+ nscd_db_entry_t db_entry;
+ struct nscd_hash *next_p;
+ struct nscd_hash *prev_p;
+} nscd_hash_t;
+
+/*
+ * This structure defines a nscd database which
+ * is implemented as an array of nscd_hash_t.
+ */
+struct nscd_db_s {
+ int array_size; /* number of elements in hash_tbl_p */
+ nscd_hash_t **hash_tbl_p;
+};
+
+/*
+ * This cookie structure is used to iterate through the
+ * database entries contained in a nscd database.
+ */
+struct cookie {
+ int idx; /* the current bucket */
+ nscd_hash_t *hash; /* the current hash entry */
+ nscd_db_t *db; /* the database */
+};
+
+/*
+ * FUNCTION: calc_hash
+ *
+ * Calculate a hash for a string based on the elf_hash
+ * algorithm, hash is case insensitive. Uses tolower
+ * instead of _tolower because of I18N.
+ */
+static unsigned long
+calc_hash(
+ const char *str)
+{
+ unsigned int hval = 0;
+ char ch;
+
+ while (*str != NULL) {
+ unsigned int g;
+
+ ch = (char)*str++;
+ if (isupper(ch))
+ ch = _tolower(ch);
+ hval = (hval << 4) + ch;
+ if ((g = (hval & 0xf0000000)) != 0)
+ hval ^= g >> 24;
+ hval &= ~g;
+ }
+ return ((unsigned long)hval);
+}
+
+/*
+ * FUNCTION: scan_hash
+ *
+ * Scan a hash table for a matching hash entry. Assume 'str' is
+ * not NULL. If option is NSCD_GET_NEXT_DB_ENTRY and id_num
+ * is less than zero, then treats the option as NSCD_GET_FIRST_DB_ENTRY.
+ */
+
+static const nscd_hash_t *
+scan_hash(
+ int type,
+ const char *str,
+ const nscd_hash_t *idx_p,
+ nscd_db_option_t option,
+ int id_num)
+{
+ int id_matched = 0;
+ nscd_db_entry_t *db_entry;
+
+ while (idx_p != NULL) {
+ db_entry = &((nscd_hash_t *)idx_p)->db_entry;
+ if (db_entry->type == type) {
+ if (strcasecmp(str, db_entry->name) == 0) {
+ switch (option) {
+ case NSCD_GET_FIRST_DB_ENTRY:
+ return (idx_p);
+ case NSCD_GET_EXACT_DB_ENTRY:
+ if (id_num == db_entry->id_num)
+ return (idx_p);
+ break;
+ case NSCD_GET_NEXT_DB_ENTRY:
+ if (id_num < 0)
+ return (idx_p);
+ if (id_matched == 1)
+ return (idx_p);
+ if (id_num == db_entry->id_num)
+ id_matched = 1;
+ break;
+ }
+ }
+ }
+ idx_p = idx_p->next_p;
+ }
+ return (NULL);
+}
+
+/*
+ * FUNCTION: _nscd_get_db_entry
+ *
+ * Find a nscd database entry from a nscd database.
+ */
+const nscd_db_entry_t *
+_nscd_get_db_entry(
+ const nscd_db_t *db,
+ int type,
+ const char *str,
+ nscd_db_option_t option,
+ int id_num)
+{
+ unsigned long hash;
+ const nscd_hash_t *idx_p, *hash_p;
+
+ if (db == NULL || str == NULL)
+ return (NULL);
+
+ hash = calc_hash(str);
+ idx_p = db->hash_tbl_p[hash % db->array_size];
+
+ hash_p = scan_hash(type, str, idx_p, option, id_num);
+
+ return (&hash_p->db_entry);
+}
+
+/*
+ * FUNCTION: _nscd_add_db_entry
+ *
+ * Add a nscd database entry to a nscd database. This function
+ * is not MT safe. The caller should lock the database to
+ * prevent concurrent updates done by other threads.
+ */
+nscd_rc_t
+_nscd_add_db_entry(
+ nscd_db_t *db,
+ const char *str,
+ nscd_db_entry_t *entry,
+ nscd_db_option_t option)
+{
+ int i;
+ unsigned long hash;
+ nscd_hash_t *next_p = NULL, *prev_p = NULL;
+ nscd_hash_t *idx_p, *hash_entry;
+ nscd_db_entry_t *db_entry;
+
+ /* find the bucket */
+ hash = calc_hash(str);
+ i = hash % db->array_size;
+ idx_p = db->hash_tbl_p[i];
+
+ /* can not replace nothing */
+ if (idx_p == NULL)
+ if (option == NSCD_ADD_DB_ENTRY_REPLACE)
+ return (NSCD_DB_ENTRY_NOT_FOUND);
+
+ while (idx_p != NULL) {
+ db_entry = &idx_p->db_entry;
+ switch (option) {
+
+ case NSCD_ADD_DB_ENTRY_FIRST:
+ next_p = idx_p;
+ goto add_entry;
+
+ case NSCD_ADD_DB_ENTRY_REPLACE:
+ if (db_entry->type != entry->type)
+ goto cont;
+ if (strcasecmp(db_entry->name, str) != 0)
+ goto cont;
+
+ if (db_entry->id_num == entry->id_num) {
+ prev_p = idx_p->prev_p;
+ next_p = idx_p->next_p;
+ free(idx_p);
+ goto add_entry;
+ }
+ goto cont;
+
+ case NSCD_ADD_DB_ENTRY_IF_NONE:
+ if (db_entry->type != entry->type)
+ break;
+ if (strcasecmp(db_entry->name, str) != 0)
+ break;
+ return (NSCD_DB_ENTRY_FOUND);
+ }
+
+ if (idx_p->next_p == NULL) {
+ if (option == NSCD_ADD_DB_ENTRY_LAST ||
+ option == NSCD_ADD_DB_ENTRY_IF_NONE) {
+ prev_p = idx_p;
+ goto add_entry;
+ }
+ }
+
+ cont:
+ idx_p = idx_p->next_p;
+ }
+
+ add_entry:
+
+ /*
+ * the nscd_entry_t field should be the first field
+ * in a nscd_hash_t
+ */
+ hash_entry = (nscd_hash_t *)entry;
+
+ /* update the prev link list */
+ hash_entry->prev_p = prev_p;
+ if (prev_p == NULL)
+ db->hash_tbl_p[i] = hash_entry;
+ else
+ prev_p->next_p = hash_entry;
+
+ /* update the next link list */
+ hash_entry->next_p = next_p;
+ if (next_p != NULL)
+ next_p->prev_p = hash_entry;
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * FUNCTION: _nscd_delete_db_entry
+ *
+ * Delete a nscd database entry from a nscd database. This
+ * function is not MT safe. The caller should lock the
+ * database to prevent concurrent updates done by other
+ * threads.
+ */
+nscd_rc_t
+_nscd_delete_db_entry(
+ nscd_db_t *db,
+ int type,
+ const char *str,
+ nscd_db_option_t option,
+ int id_num)
+{
+ int i;
+ int del_more = 0;
+ unsigned long hash;
+ nscd_hash_t *idx_p, *next_p = NULL, *prev_p = NULL;
+ nscd_db_entry_t *db_entry;
+
+ /* find the bucket */
+ hash = calc_hash(str);
+ i = hash % db->array_size;
+ idx_p = db->hash_tbl_p[i];
+
+ /* delete nothing always works */
+ if (idx_p == NULL)
+ return (NSCD_SUCCESS);
+
+ while (idx_p != NULL) {
+ db_entry = &idx_p->db_entry;
+ if (db_entry->type != type)
+ goto cont;
+ if (strcasecmp(db_entry->name, str) != 0)
+ goto cont;
+
+ switch (option) {
+
+ case NSCD_DEL_FIRST_DB_ENTRY:
+ prev_p = idx_p->prev_p;
+ next_p = idx_p->next_p;
+ del_more = 0;
+ break;
+
+ case NSCD_DEL_EXACT_DB_ENTRY:
+ if (db_entry->id_num == id_num) {
+ prev_p = idx_p->prev_p;
+ next_p = idx_p->next_p;
+ del_more = 0;
+ } else
+ goto cont;
+ break;
+
+ case NSCD_DEL_ALL_DB_ENTRY:
+ prev_p = idx_p->prev_p;
+ next_p = idx_p->next_p;
+ break;
+ }
+
+ if (prev_p == NULL)
+ db->hash_tbl_p[i] = next_p;
+ else
+ prev_p->next_p = next_p;
+
+ if (next_p != NULL)
+ next_p->prev_p = prev_p;
+
+ free(idx_p);
+
+ if (del_more == 0)
+ break;
+ /*
+ * only when option == NSCD_DEL_ALL_DB_ENTRY
+ * will we get here. next_p should be set to
+ * idx_p->next_p beforehand
+ */
+ idx_p = next_p;
+ continue;
+
+ cont:
+
+ idx_p = idx_p->next_p;
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * FUNCTION: _nscd_alloc_db_entry
+ *
+ * Allocate and return the memory for a database entry
+ * so the caller can insert data and then add it to the
+ * database.
+ */
+nscd_db_entry_t *
+_nscd_alloc_db_entry(
+ int type,
+ const char *name,
+ int dataSize,
+ int num_data,
+ int num_array)
+{
+ int size;
+ int array_o, data_o;
+ nscd_hash_t *hash;
+ void *p;
+
+ /* first part: hash data structure and name string */
+ size = sizeof (*hash) + strlen(name) + 1;
+ array_o = size = roundup(size);
+
+ /* second part: pointer array to data */
+ size += (num_data + num_array) * sizeof (void **);
+ size = roundup(size);
+
+ /* third part: actual data */
+ data_o = size;
+ size += dataSize;
+
+ /* allocate the memory */
+ hash = (nscd_hash_t *)calloc(1, size);
+
+ if (hash == NULL)
+ return (NULL);
+
+ /* init the entry based on caller's input */
+ hash->db_entry.num_data = num_data;
+ hash->db_entry.num_array = num_array;
+ hash->db_entry.type = type;
+ hash->db_entry.name = (char *)hash + sizeof (*hash);
+ p = (char *)hash + array_o;
+ hash->db_entry.data_array = (void **)p;
+ *(hash->db_entry.data_array) = (char *)hash + data_o;
+ (void) strcpy(hash->db_entry.name, name);
+
+ return (&hash->db_entry);
+}
+
+/*
+ * FUNCTION: _nscd_delete_db_entry_cookie
+ *
+ * Delete a database entry using the information from
+ * the input 'cookie'.
+ */
+void
+_nscd_delete_db_entry_cookie(
+ nscd_db_t *db,
+ void **cookie)
+{
+ nscd_hash_t *hp;
+ struct cookie *c;
+
+ /* snaity check */
+ if (cookie == NULL || *cookie == NULL || db == NULL)
+ return;
+ c = *cookie;
+
+ /* more snaity check */
+ if (db != c->db || c->hash == NULL ||
+ c->idx < 0 || c->idx >= db->array_size)
+ return;
+
+ /* retrieve the hash entry from the cookie */
+ hp = c->hash;
+
+ /*
+ * Update the next/previous link list.
+ * Need to update c->hash as well, in case
+ * the cookie is also used in a walk-db
+ * loop. This is to make sure that the
+ * next _nscd_walk_db() call will
+ * find the (updated) next hash entry in line.
+ */
+ if (hp->prev_p == NULL) {
+ /*
+ * make sure the current bucket will be
+ * walked again if _nscd_walk_db is
+ * called next
+ */
+ c->hash = NULL;
+ db->hash_tbl_p[c->idx] = hp->next_p;
+ c->idx--;
+
+ } else {
+ c->hash = hp->prev_p;
+ hp->prev_p->next_p = hp->next_p;
+ }
+ if (hp->next_p != NULL)
+ hp->next_p->prev_p = hp->prev_p;
+
+ /* delete the entry */
+ free(hp);
+}
+
+/*
+ * FUNCTION: _nscd_alloc_db
+ *
+ * Allocate the space for a nscd database.
+ *
+ * The input argument, size, indicates the size of the database.
+ * NSCD_DB_SIZE_LARGE specifies an bucket array of size 67,
+ * NSCD_DB_SIZE_MEDIUM specifies an bucket array of size 37,
+ * NSCD_DB_SIZE_SMALL specifies an bucket array of size 13,
+ * NSCD_DB_SIZE_TINY specifies an bucket array of size 3.
+ */
+nscd_db_t *
+_nscd_alloc_db(
+ int size)
+{
+ int sz;
+ nscd_db_t *db;
+
+ /* allocate the database */
+ db = (nscd_db_t *)calloc(1, sizeof (nscd_db_t));
+ if (db == NULL)
+ return (NULL);
+
+ /* allocate the bucket array */
+ if (size == NSCD_DB_SIZE_LARGE)
+ sz = 67;
+ else if (size == NSCD_DB_SIZE_MEDIUM)
+ sz = 37;
+ else if (size == NSCD_DB_SIZE_SMALL)
+ sz = 13;
+ else if (size == NSCD_DB_SIZE_TINY)
+ sz = 3;
+ db->hash_tbl_p = (nscd_hash_t **)calloc(sz + 1,
+ sizeof (nscd_hash_t *));
+ if (db->hash_tbl_p == NULL) {
+ free(db);
+ return (NULL);
+ }
+
+ db->array_size = sz;
+
+ return (db);
+}
+
+/*
+ * FUNCTION: _nscd_free_db
+ *
+ * Delete a nscd database.
+ */
+void
+_nscd_free_db(
+ nscd_db_t *db)
+{
+ int i;
+ nscd_hash_t *hp, *next_p;
+
+ /*
+ * find non-empty buckets and for each one of them,
+ * delete all the database entries in it's link list
+ */
+ for (i = 0; i < db->array_size; i++) {
+
+ hp = db->hash_tbl_p[i];
+
+ while (hp != NULL) {
+ next_p = hp->next_p;
+ free(hp);
+ hp = next_p;
+ }
+ }
+
+ /* free the bucket array */
+ free(db->hash_tbl_p);
+
+ free(db);
+}
+
+/*
+ * FUNCTION: _nscd_walk_db
+ *
+ * Iterate through the database entries contained in
+ * a nscd database and return one entry at a time.
+ * The cookie structure is used to indicate the
+ * location of the returned entry for the next call
+ * to this function. For the very first call, *cookie
+ * should be set to NULL. For subsequent calls, the one
+ * returned by the previous call sould be used.
+ */
+nscd_db_entry_t *
+_nscd_walk_db(
+ nscd_db_t *db,
+ void **cookie)
+{
+ struct cookie *c;
+
+ /* sanity check */
+ if (cookie == NULL || db == NULL)
+ return (NULL);
+
+ if (*cookie != NULL) {
+
+ c = *cookie;
+
+ /*
+ * More sanity check. _nscd_delete_db_entry_cookie()
+ * could change c->idx to -1.
+ */
+ if (db != c->db ||
+ c->idx < -1 || c->idx >= db->array_size)
+ return (NULL);
+
+ /* is there a next entry ? */
+ if (c->hash != NULL)
+ c->hash = c->hash->next_p;
+
+ /* yes, return it */
+ if (c->hash != NULL) {
+ return (&c->hash->db_entry);
+ }
+ } else {
+ c = (struct cookie *)calloc(1, sizeof (*c));
+ if (c == NULL)
+ return (NULL);
+ c->idx = -1;
+ c->hash = NULL;
+ c->db = db;
+ }
+
+ /* find the first non-empty bucket */
+ for (c->idx++; c->idx < db->array_size; c->idx++) {
+ c->hash = db->hash_tbl_p[c->idx];
+ if (c->hash != NULL)
+ break;
+ }
+
+ /* no (more) non-empty bucket, we are done */
+ if (c->hash == NULL) {
+ free(c);
+ *cookie = NULL;
+ return (NULL);
+ }
+
+ *cookie = c;
+ return (&c->hash->db_entry);
+}
diff --git a/usr/src/cmd/nscd/nscd_door.c b/usr/src/cmd/nscd/nscd_door.c
new file mode 100644
index 0000000000..87640baf02
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_door.c
@@ -0,0 +1,353 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#include <string.h>
+#include <door.h>
+#include <sys/mman.h>
+#include "nscd_door.h"
+#include "nscd_log.h"
+#include <getxby_door.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+
+static void
+initdoor(void *buf, int *doorfd)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ door_info_t doori;
+ char *me = "initdoor";
+
+ *doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0);
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door is %s (fd is %d)\n", NAME_SERVICE_DOOR,
+ *doorfd);
+
+ if (*doorfd == -1)
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, errno);
+
+ if (door_info(*doorfd, &doori) < 0 ||
+ (doori.di_attributes & DOOR_REVOKED) ||
+ doori.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {
+
+ /*
+ * we should close doorfd because we just opened it
+ */
+ (void) close(*doorfd);
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door %d not valid\n", *doorfd);
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, ECONNREFUSED);
+ }
+
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+}
+
+/* general door call functions used by nscd */
+
+static nss_status_t
+copy_output(void *outdata, int outdlen,
+ nss_pheader_t *phdr, nss_pheader_t *outphdr)
+{
+ void *dp;
+ nss_status_t ret = NSS_SUCCESS;
+ char *me = "copy_output";
+
+ if (outdata != NULL && phdr->data_off > 0 && phdr->data_len > 0) {
+ if (phdr->data_len <= outdlen) {
+ dp = (char *)phdr + phdr->data_off;
+ (void) memmove(outdata, dp, phdr->data_len);
+ } else {
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "output buffer not large enough "
+ " should be > %d but is %d\n",
+ phdr->data_len, outdlen);
+
+ if (outphdr != NULL) {
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV,
+ 0, NSCD_INVALID_ARGUMENT);
+ NSCD_COPY_STATUS(outphdr, phdr);
+ }
+ ret = NSS_NSCD_PRIV;
+ }
+ }
+
+ return (ret);
+}
+
+
+nss_status_t
+_nscd_doorcall(int callnum)
+{
+ nss_pheader_t phdr;
+ void *dptr;
+ size_t ndata;
+ size_t adata;
+ int ret;
+ char *me = "_nscd_doorcall";
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "processing door call %d ...\n", callnum);
+
+ phdr.nsc_callnumber = callnum;
+ ndata = sizeof (phdr);
+ adata = sizeof (phdr);
+ dptr = (void *)&phdr;
+ ret = _nsc_trydoorcall(&dptr, &ndata, &adata);
+
+ if (ret != NSS_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (%d) failed (status = %d, error = %s)\n",
+ callnum, ret, strerror(NSCD_GET_ERRNO(&phdr)));
+ }
+
+ return (ret);
+}
+
+nss_status_t
+_nscd_doorcall_data(int callnum, void *indata, int indlen,
+ void *outdata, int outdlen, nss_pheader_t *phdr)
+{
+ void *uptr;
+ size_t buflen;
+ void *dptr;
+ void *datap;
+ size_t ndata;
+ size_t adata;
+ nss_pheader_t *phdr_d;
+ int ret;
+ char *me = "_nscd_doorcall_data";
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "processing door call %d ...\n", callnum);
+
+ /* allocate door buffer from the stack */
+ NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
+ dptr = uptr;
+ ndata = buflen;
+ adata = buflen;
+ datap = NSCD_N2N_DOOR_DATA(void, dptr);
+ if (indata != NULL)
+ (void) memmove(datap, indata, indlen);
+
+ ret = _nsc_trydoorcall(&dptr, &ndata, &adata);
+
+ phdr_d = (nss_pheader_t *)dptr;
+ if (ret != NSS_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (%d) failed (status = %d, error = %s)\n",
+ callnum, ret, strerror(NSCD_GET_ERRNO(phdr_d)));
+ } else {
+ if (phdr != NULL) {
+ NSCD_COPY_STATUS(phdr, phdr_d);
+ }
+ ret = copy_output(outdata, outdlen, phdr_d, phdr);
+ }
+
+ /* if new buffer allocated for this door call, free it */
+ if (dptr != uptr)
+ (void) munmap(dptr, ndata);
+
+ return (ret);
+}
+
+nss_status_t
+_nscd_doorcall_fd(int fd, int callnum, void *indata, int indlen,
+ void *outdata, int outdlen, nss_pheader_t *phdr)
+{
+ void *uptr;
+ void *dptr;
+ void *datap;
+ size_t ndata;
+ size_t adata;
+ size_t buflen;
+ door_arg_t param;
+ int ret, errnum;
+ nss_pheader_t *phdr_d;
+ char *me = "_nscd_doorcall_fd";
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "processing door call %d (fd = %d)...\n", callnum, fd);
+
+ /* allocate door buffer from the stack */
+ NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
+ dptr = uptr;
+ ndata = buflen;
+ adata = buflen;
+ datap = NSCD_N2N_DOOR_DATA(void, dptr);
+ if (indata != NULL)
+ (void) memmove(datap, indata, indlen);
+
+ param.rbuf = (char *)dptr;
+ param.rsize = ndata;
+ param.data_ptr = (char *)dptr;
+ param.data_size = adata;
+ param.desc_ptr = NULL;
+ param.desc_num = 0;
+ ret = door_call(fd, &param);
+ if (ret < 0) {
+ errnum = errno;
+ /*
+ * door call did not get through, return errno
+ * if requested
+ */
+ if (phdr != NULL) {
+ NSCD_SET_STATUS(phdr, NSS_ERROR, errnum);
+ }
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (%d to %d) did not get through (%s)\n",
+ callnum, fd, strerror(errnum));
+
+ return (NSS_ERROR);
+ }
+ ndata = param.rsize;
+ dptr = (void *)param.data_ptr;
+
+ /*
+ * door call got through, check if operation failed.
+ * if so, return error info if requested
+ */
+ phdr_d = (nss_pheader_t *)dptr;
+ ret = NSCD_GET_STATUS(phdr_d);
+ if (ret != NSS_SUCCESS) {
+ if (phdr != NULL) {
+ NSCD_COPY_STATUS(phdr, phdr_d);
+ }
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (%d to %d) failed: p_status = %d, "
+ "p_errno = %s, nscd status = %d\n", callnum, fd,
+ ret, strerror(NSCD_GET_ERRNO(phdr_d)),
+ NSCD_GET_NSCD_STATUS(phdr_d));
+ } else
+ ret = copy_output(outdata, outdlen, phdr_d, phdr);
+
+ /* if new buffer allocated for this door call, free it */
+ if (dptr != uptr)
+ (void) munmap(dptr, param.rsize);
+
+
+ return (ret);
+}
+
+static void
+send_doorfd(void **dptr, size_t *ndata, size_t *adata,
+ door_desc_t *pdesc)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)*dptr;
+ door_arg_t param;
+ int ret;
+ int doorfd;
+ int errnum;
+ char *me = "send_doorfd";
+
+ initdoor(*dptr, &doorfd);
+ if (NSCD_STATUS_IS_NOT_OK(phdr))
+ return;
+
+ param.rbuf = (char *)*dptr;
+ param.rsize = *ndata;
+ param.data_ptr = (char *)*dptr;
+ param.data_size = *adata;
+ param.desc_ptr = pdesc;
+ param.desc_num = 1;
+ ret = door_call(doorfd, &param);
+ if (ret < 0) {
+ errnum = errno;
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (to fd %d) failed (%s)\n",
+ doorfd, strerror(errnum));
+ (void) close(doorfd);
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
+ }
+ *adata = param.data_size;
+ *ndata = param.rsize;
+ *dptr = (void *)param.data_ptr;
+
+ if (*adata == 0 || *dptr == NULL) {
+ (void) close(doorfd);
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no data\n");
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, ENOTCONN);
+ }
+
+ (void) close(doorfd);
+}
+
+nss_status_t
+_nscd_doorcall_sendfd(int fd, int callnum, void *indata, int indlen,
+ nss_pheader_t *phdr)
+{
+ void *uptr;
+ void *dptr;
+ void *datap;
+ size_t ndata;
+ size_t adata;
+ size_t buflen;
+ nss_pheader_t *phdr_d;
+ door_desc_t desc;
+ char *me = "_nscd_doorcall_sendfd";
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "processing door call %d (fd = %d)...\n", callnum, fd);
+
+ /* allocate door buffer from the stack */
+ NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
+ dptr = uptr;
+ ndata = buflen;
+ adata = buflen;
+ datap = NSCD_N2N_DOOR_DATA(void, dptr);
+ if (indata != NULL)
+ (void) memmove(datap, indata, indlen);
+ desc.d_attributes = DOOR_DESCRIPTOR;
+ desc.d_data.d_desc.d_descriptor = fd;
+
+ send_doorfd(&dptr, &ndata, &adata, &desc);
+
+ phdr_d = (nss_pheader_t *)dptr;
+ if (NSCD_STATUS_IS_NOT_OK(phdr_d)) {
+ if (phdr != NULL)
+ *phdr = *phdr_d;
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door call (%d) failed (status = %d, error = %s)\n",
+ callnum, NSCD_GET_STATUS(phdr_d),
+ strerror(NSCD_GET_ERRNO(phdr_d)));
+ }
+
+ return (NSCD_GET_STATUS(phdr_d));
+}
diff --git a/usr/src/cmd/nscd/nscd_door.h b/usr/src/cmd/nscd/nscd_door.h
new file mode 100644
index 0000000000..382968f5e1
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_door.h
@@ -0,0 +1,175 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_DOOR_H
+#define _NSCD_DOOR_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Definitions for nscd to nscd door interfaces
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <alloca.h>
+#include <nss_dbdefs.h>
+
+/* door for Trusted Extensions */
+#define TSOL_NAME_SERVICE_DOOR "/var/tsol/doors/name_service_door"
+
+/* nscd v2 nscd -> nscd call numbers */
+#define NSCD_PING (NSCD_CALLCAT_N2N|0x01)
+#define NSCD_GETADMIN (NSCD_CALLCAT_N2N|0x02)
+#define NSCD_SETADMIN (NSCD_CALLCAT_N2N|0x03)
+#define NSCD_GETPUADMIN (NSCD_CALLCAT_N2N|0x04)
+#define NSCD_SETPUADMIN (NSCD_CALLCAT_N2N|0x05)
+#define NSCD_KILLSERVER (NSCD_CALLCAT_N2N|0x06)
+
+#define NSCD_IMHERE (NSCD_CALLCAT_N2N|0x10) /* IMHERE+WHOAMI */
+#define NSCD_FORK (NSCD_CALLCAT_N2N|0x20)
+#define NSCD_SETUID (NSCD_CALLCAT_N2N|0x30)
+#define NSCD_KILL (NSCD_CALLCAT_N2N|0x40)
+#define NSCD_PULSE (NSCD_CALLCAT_N2N|0x50)
+#define NSCD_REFRESH (NSCD_CALLCAT_N2N|0x60)
+
+/* nscd v2 nscd identities */
+
+#define NSCD_MAIN 0x00000001
+#define NSCD_FORKER 0x00000002
+#define NSCD_CHILD 0x00000004
+#define NSCD_WHOAMI 0x0000000F
+
+#define NSCD_ALLOC_DOORBUF(cn, dsz, uptr, usz) \
+ usz = (sizeof (nss_pheader_t) + (dsz)); \
+ uptr = alloca(usz); \
+ (void) memset(uptr, 0, usz); \
+ ((nss_pheader_t *)uptr)->nsc_callnumber = (cn); \
+ ((nss_pheader_t *)uptr)->pbufsiz = usz; \
+ ((nss_pheader_t *)uptr)->data_off = sizeof (nss_pheader_t);
+
+#define NSCD_N2N_DOOR_DATA(type, buf) \
+ (type *)((void *)(((char *)(buf)) + sizeof (nss_pheader_t)))
+
+#define NSCD_N2N_DOOR_BUF_SIZE(struct) \
+ sizeof (nss_pheader_t) + sizeof (struct)
+
+#define NSCD_SET_STATUS(ph, st, errno) \
+ { \
+ int e = errno; \
+ (ph)->p_status = st; \
+ if (e != -1) \
+ (ph)->p_errno = e; \
+ }
+
+#define NSCD_SET_HERRNO(ph, herrno) \
+ (ph)->p_herrno = herrno;
+
+
+#define NSCD_RETURN_STATUS(ph, st, errno) \
+ { \
+ int e = errno; \
+ (ph)->p_status = st; \
+ if (e != -1) \
+ (ph)->p_errno = e; \
+ return; \
+ }
+
+#define NSCD_SET_STATUS_SUCCESS(ph) \
+ (ph)->p_status = NSS_SUCCESS; \
+ (ph)->p_errno = 0;
+
+#define NSCD_RETURN_STATUS_SUCCESS(ph) \
+ (ph)->p_status = NSS_SUCCESS; \
+ (ph)->p_errno = 0; \
+ return;
+
+#define NSCD_SET_N2N_STATUS(ph, st, errno, n2nst) \
+ { \
+ int e = errno; \
+ (ph)->p_status = st; \
+ if (e != -1) \
+ (ph)->p_errno = e; \
+ (ph)->nscdpriv = n2nst; \
+ }
+
+#define NSCD_RETURN_N2N_STATUS(ph, st, errno, n2nst) \
+ { \
+ int e = errno; \
+ (ph)->p_status = st; \
+ if (e != -1) \
+ (ph)->p_errno = e; \
+ (ph)->nscdpriv = n2nst; \
+ return; \
+ }
+
+#define NSCD_STATUS_IS_OK(ph) \
+ (((ph)->p_status) == NSS_SUCCESS)
+
+#define NSCD_STATUS_IS_NOT_OK(ph) \
+ (((ph)->p_status) != NSS_SUCCESS)
+
+#define NSCD_GET_STATUS(ph) \
+ (((nss_pheader_t *)(ph))->p_status)
+
+#define NSCD_GET_ERRNO(ph) \
+ (((nss_pheader_t *)(ph))->p_errno)
+
+#define NSCD_GET_HERRNO(ph) \
+ (((nss_pheader_t *)(ph))->p_herrno)
+
+#define NSCD_GET_NSCD_STATUS(ph) \
+ (((nss_pheader_t *)(ph))->nscdpriv)
+
+#define NSCD_CLEAR_STATUS(ph) \
+ (ph)->p_status = 0; \
+ (ph)->p_errno = 0; \
+ (ph)->nscdpriv = 0;
+
+#define NSCD_COPY_STATUS(ph, ph1) \
+ (ph)->p_status = (ph1)->p_status; \
+ (ph)->p_errno = (ph1)->p_errno; \
+ (ph)->nscdpriv = (ph1)->nscdpriv;
+
+nss_status_t _nscd_doorcall(int callnum);
+nss_status_t _nscd_doorcall_data(int callnum, void *indata,
+ int indlen, void *outdata, int outdlen,
+ nss_pheader_t *phdr);
+
+nss_status_t _nscd_doorcall_fd(int fd, int callnum, void *indata,
+ int indlen, void *outdata, int outdlen,
+ nss_pheader_t *phdr);
+
+nss_status_t _nscd_doorcall_sendfd(int fd, int callnum,
+ void *indata, int indlen, nss_pheader_t *phdr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_DOOR_H */
diff --git a/usr/src/cmd/nscd/nscd_frontend.c b/usr/src/cmd/nscd/nscd_frontend.c
new file mode 100644
index 0000000000..7f718111e9
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_frontend.c
@@ -0,0 +1,1150 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <alloca.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <errno.h>
+#include <door.h>
+#include <zone.h>
+#include <resolv.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "nscd_common.h"
+#include "nscd_door.h"
+#include "nscd_config.h"
+#include "nscd_switch.h"
+#include "nscd_log.h"
+#include "nscd_selfcred.h"
+#include "nscd_frontend.h"
+#include "nscd_admin.h"
+
+static void rts_mon(void);
+static void keep_open_dns_socket(void);
+
+extern nsc_ctx_t *cache_ctx_p[];
+
+/*
+ * Current active Configuration data for the frontend component
+ */
+static nscd_cfg_global_frontend_t frontend_cfg_g;
+static nscd_cfg_frontend_t *frontend_cfg;
+
+static int max_servers = 0;
+static int max_servers_set = 0;
+static int per_user_is_on = 1;
+
+static char *main_execname;
+static char **main_argv;
+extern int _whoami;
+extern long activity;
+extern mutex_t activity_lock;
+
+static sema_t common_sema;
+
+static thread_key_t lookup_state_key;
+static mutex_t create_lock = DEFAULTMUTEX;
+static int num_servers = 0;
+static thread_key_t server_key;
+
+/*
+ * Bind a TSD value to a server thread. This enables the destructor to
+ * be called if/when this thread exits. This would be a programming
+ * error, but better safe than sorry.
+ */
+/*ARGSUSED*/
+static void *
+server_tsd_bind(void *arg)
+{
+ static void *value = 0;
+
+ /* disable cancellation to avoid hangs if server threads disappear */
+ (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ (void) thr_setspecific(server_key, value);
+ (void) door_return(NULL, 0, NULL, 0);
+
+ /* make lint happy */
+ return (NULL);
+}
+
+/*
+ * Server threads are created here.
+ */
+/*ARGSUSED*/
+static void
+server_create(door_info_t *dip)
+{
+ (void) mutex_lock(&create_lock);
+ if (++num_servers > max_servers) {
+ num_servers--;
+ (void) mutex_unlock(&create_lock);
+ return;
+ }
+ (void) mutex_unlock(&create_lock);
+ (void) thr_create(NULL, 0, server_tsd_bind, NULL,
+ THR_BOUND|THR_DETACHED, NULL);
+}
+
+/*
+ * Server thread are destroyed here
+ */
+/*ARGSUSED*/
+static void
+server_destroy(void *arg)
+{
+ (void) mutex_lock(&create_lock);
+ num_servers--;
+ (void) mutex_unlock(&create_lock);
+}
+
+/*
+ * get clearance
+ */
+int
+_nscd_get_clearance(sema_t *sema) {
+ if (sema_trywait(&common_sema) == 0) {
+ (void) thr_setspecific(lookup_state_key, NULL);
+ return (0);
+ }
+
+ if (sema_trywait(sema) == 0) {
+ (void) thr_setspecific(lookup_state_key, (void*)1);
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
+ * release clearance
+ */
+int
+_nscd_release_clearance(sema_t *sema) {
+ int which;
+
+ (void) thr_getspecific(lookup_state_key, (void**)&which);
+ if (which == 0) /* from common pool */ {
+ (void) sema_post(&common_sema);
+ return (0);
+ }
+
+ (void) sema_post(sema);
+ return (1);
+}
+
+static void
+dozip(void)
+{
+ /* not much here */
+}
+
+static void
+restart_if_cfgfile_changed()
+{
+
+ static mutex_t nsswitch_lock = DEFAULTMUTEX;
+ static time_t last_nsswitch_check = 0;
+ static time_t last_nsswitch_modified = 0;
+ static time_t last_resolv_modified = 0;
+ time_t now = time(NULL);
+ char *me = "restart_if_cfgfile_changed";
+
+ if (now - last_nsswitch_check <= _NSC_FILE_CHECK_TIME)
+ return;
+
+ (void) mutex_lock(&nsswitch_lock);
+
+ if (now - last_nsswitch_check > _NSC_FILE_CHECK_TIME) {
+ struct stat nss_buf;
+ struct stat res_buf;
+
+ last_nsswitch_check = now;
+
+ (void) mutex_unlock(&nsswitch_lock); /* let others continue */
+
+ /*
+ * This code keeps us from statting resolv.conf
+ * if it doesn't exist, yet prevents us from ignoring
+ * it if it happens to disappear later on for a bit.
+ */
+
+ if (last_resolv_modified >= 0) {
+ if (stat("/etc/resolv.conf", &res_buf) < 0) {
+ if (last_resolv_modified == 0)
+ last_resolv_modified = -1;
+ else
+ res_buf.st_mtime = last_resolv_modified;
+ } else if (last_resolv_modified == 0) {
+ last_resolv_modified = res_buf.st_mtime;
+ }
+ }
+
+ if (stat("/etc/nsswitch.conf", &nss_buf) < 0) {
+
+ /*EMPTY*/;
+
+ } else if (last_nsswitch_modified == 0) {
+
+ last_nsswitch_modified = nss_buf.st_mtime;
+
+ } else if ((last_nsswitch_modified < nss_buf.st_mtime) ||
+ ((last_resolv_modified > 0) &&
+ (last_resolv_modified < res_buf.st_mtime))) {
+ static mutex_t exit_lock = DEFAULTMUTEX;
+ char *fmri;
+
+ /*
+ * if in self cred mode, kill the forker and
+ * child nscds
+ */
+ if (_nscd_is_self_cred_on(0, NULL)) {
+ _nscd_kill_forker();
+ _nscd_kill_all_children();
+ }
+
+ /*
+ * time for restart
+ */
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO)
+ (me, "nscd restart due to %s or %s change\n",
+ "/etc/nsswitch.conf", "resolv.conf");
+ /*
+ * try to restart under smf
+ */
+ if ((fmri = getenv("SMF_FMRI")) == NULL) {
+ /* not running under smf - reexec */
+ (void) execv(main_execname, main_argv);
+ exit(1); /* just in case */
+ }
+
+ /* prevent multiple restarts */
+ (void) mutex_lock(&exit_lock);
+
+ if (smf_restart_instance(fmri) == 0)
+ (void) sleep(10); /* wait a bit */
+ exit(1); /* give up waiting for resurrection */
+ }
+
+ } else
+ (void) mutex_unlock(&nsswitch_lock);
+}
+
+uid_t
+_nscd_get_client_euid()
+{
+ ucred_t *uc = NULL;
+ uid_t id;
+ char *me = "get_client_euid";
+
+ if (door_ucred(&uc) != 0) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred: %s\n", strerror(errno));
+ return ((uid_t)-1);
+ }
+
+ id = ucred_geteuid(uc);
+ ucred_free(uc);
+ return (id);
+}
+
+static void
+N2N_check_priv(
+ void *buf,
+ char *dc_str)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ ucred_t *uc = NULL;
+ const priv_set_t *eset;
+ zoneid_t zoneid;
+ int errnum;
+ char *me = "N2N_check_priv";
+
+ if (door_ucred(&uc) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred: %s\n", strerror(errno));
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
+ }
+
+ eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
+ zoneid = ucred_getzoneid(uc);
+
+ if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) ||
+ eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) :
+ ucred_geteuid(uc) != 0) {
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
+ (me, "%s call failed(cred): caller pid %d, uid %d, "
+ "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
+ ucred_getruid(uc), ucred_geteuid(uc), zoneid);
+ ucred_free(uc);
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES);
+ }
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nscd received %s cmd from pid %d, uid %d, "
+ "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
+ ucred_getruid(uc), ucred_geteuid(uc), zoneid);
+
+ ucred_free(uc);
+
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+}
+
+static void
+APP_check_cred(
+ void *buf,
+ pid_t *pidp,
+ char *dc_str)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ ucred_t *uc = NULL;
+ uid_t ruid;
+ uid_t euid;
+ int errnum;
+ char *me = "APP_check_cred";
+
+ if (door_ucred(&uc) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred: %s\n", strerror(errno));
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
+ }
+
+ if (NSS_PACKED_CRED_CHECK(buf, ruid = ucred_getruid(uc),
+ euid = ucred_geteuid(uc))) {
+ if (pidp != NULL)
+ *pidp = ucred_getpid(uc);
+ ucred_free(uc);
+
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+ }
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
+ (me, "%s call failed: caller pid %d, ruid %d, "
+ "euid %d, header ruid %d, header euid %d\n", dc_str,
+ (pidp != NULL) ? *pidp : -1, ruid, euid,
+ ((nss_pheader_t *)(buf))->p_ruid, ((nss_pheader_t *)(buf))->p_euid);
+
+
+ ucred_free(uc);
+
+ NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES);
+}
+
+static void
+lookup(char *argp, size_t arg_size)
+{
+ nsc_lookup_args_t largs;
+ char space[NSCD_LOOKUP_BUFSIZE];
+ nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp;
+
+ NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space,
+ sizeof (space));
+
+ (void) memset(&largs, 0, sizeof (largs));
+ largs.buffer = argp;
+ largs.bufsize = arg_size;
+ nsc_lookup(&largs, 0);
+
+ /*
+ * only the PUN needs to keep track of the
+ * activity count to determine when to
+ * terminate itself
+ */
+ if (_whoami == NSCD_CHILD) {
+ (void) mutex_lock(&activity_lock);
+ ++activity;
+ (void) mutex_unlock(&activity_lock);
+ }
+
+ NSCD_SET_RETURN_ARG(phdr, arg_size);
+ (void) door_return(argp, arg_size, NULL, 0);
+}
+
+static void
+getent(char *argp, size_t arg_size)
+{
+ char space[NSCD_LOOKUP_BUFSIZE];
+ nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp;
+
+ NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr,
+ space, sizeof (space));
+
+ nss_pgetent(argp, arg_size);
+
+ NSCD_SET_RETURN_ARG(phdr, arg_size);
+ (void) door_return(argp, arg_size, NULL, 0);
+}
+
+static int
+is_db_per_user(void *buf, char *dblist)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ nss_dbd_t *pdbd;
+ char *dbname, *dbn;
+ int len;
+
+ /* copy db name into a temp buffer */
+ pdbd = (nss_dbd_t *)((void *)((char *)buf + phdr->dbd_off));
+ dbname = (char *)pdbd + pdbd->o_name;
+ len = strlen(dbname);
+ dbn = alloca(len + 2);
+ (void) memcpy(dbn, dbname, len);
+
+ /* check if <dbname> + ',' can be found in the dblist string */
+ dbn[len] = ',';
+ dbn[len + 1] = '\0';
+ if (strstr(dblist, dbn) != NULL)
+ return (1);
+
+ /*
+ * check if <dbname> can be found in the last part
+ * of the dblist string
+ */
+ dbn[len] = '\0';
+ if (strstr(dblist, dbn) != NULL)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Check to see if all conditions are met for processing per-user
+ * requests. Returns 1 if yes, -1 if backend is not configured,
+ * 0 otherwise.
+ */
+static int
+need_per_user_door(void *buf, int whoami, uid_t uid, char **dblist)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+
+ NSCD_SET_STATUS_SUCCESS(phdr);
+
+ /* if already a per-user nscd, no need to get per-user door */
+ if (whoami == NSCD_CHILD)
+ return (0);
+
+ /* forker shouldn't be asked */
+ if (whoami == NSCD_FORKER) {
+ NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
+ return (0);
+ }
+
+ /* if door client is root, no need for a per-user door */
+ if (uid == 0)
+ return (0);
+
+ /*
+ * if per-user lookup is not configured, no per-user
+ * door available
+ */
+ if (_nscd_is_self_cred_on(0, dblist) == 0)
+ return (-1);
+
+ /*
+ * if per-user lookup is not configured for the db,
+ * don't bother
+ */
+ if (is_db_per_user(phdr, *dblist) == 0)
+ return (0);
+
+ return (1);
+}
+
+static void
+if_selfcred_return_per_user_door(char *argp, size_t arg_size,
+ door_desc_t *dp, int whoami)
+{
+ nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp);
+ char *dblist;
+ int door = -1;
+ int rc = 0;
+ door_desc_t desc;
+ char space[1024*4];
+
+ /*
+ * check to see if self-cred is configured and
+ * need to return an alternate PUN door
+ */
+ if (per_user_is_on == 1) {
+ rc = need_per_user_door(argp, whoami,
+ _nscd_get_client_euid(), &dblist);
+ if (rc == -1)
+ per_user_is_on = 0;
+ }
+ if (rc <= 0) {
+ /*
+ * self-cred not configured, and no error detected,
+ * return to continue the door call processing
+ */
+ if (NSCD_STATUS_IS_OK(phdr))
+ return;
+ else
+ /*
+ * configured but error detected,
+ * stop the door call processing
+ */
+ (void) door_return(argp, phdr->data_off, NULL, 0);
+ }
+
+ /* get the alternate PUN door */
+ _nscd_proc_alt_get(argp, &door);
+ if (NSCD_GET_STATUS(phdr) != NSS_ALTRETRY) {
+ (void) door_return(argp, phdr->data_off, NULL, 0);
+ }
+
+ /* return the alternate door descriptor */
+ (void) memcpy(space, phdr, NSCD_PHDR_LEN(phdr));
+ argp = space;
+ phdr = (nss_pheader_t *)(void *)space;
+ dp = &desc;
+ dp->d_attributes = DOOR_DESCRIPTOR;
+ dp->d_data.d_desc.d_descriptor = door;
+ phdr->data_len = strlen(dblist) + 1;
+ (void) strcpy(((char *)phdr) + NSCD_PHDR_LEN(phdr), dblist);
+
+ arg_size = NSCD_PHDR_LEN(phdr) + NSCD_DATA_LEN(phdr);
+ (void) door_return(argp, arg_size, dp, 1);
+}
+
+/*ARGSUSED*/
+static void
+switcher(void *cookie, char *argp, size_t arg_size,
+ door_desc_t *dp, uint_t n_desc)
+{
+ int iam;
+ pid_t ent_pid = -1;
+ nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp);
+ void *uptr;
+ int buflen, len;
+ int callnum;
+ char *me = "switcher";
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "switcher ...\n");
+
+ if (argp == DOOR_UNREF_DATA) {
+ (void) printf("Door Slam... exiting\n");
+ exit(0);
+ }
+
+ if (argp == NULL) { /* empty door call */
+ (void) door_return(NULL, 0, 0, 0); /* return the favor */
+ }
+
+ /*
+ * need to restart if main nscd and config file(s) changed
+ */
+ if (_whoami == NSCD_MAIN)
+ restart_if_cfgfile_changed();
+
+ if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) {
+ switch (phdr->nsc_callnumber) {
+ case NSCD_SEARCH:
+
+ /* if a fallback to main nscd, skip per-user setup */
+ if (phdr->p_status != NSS_ALTRETRY)
+ if_selfcred_return_per_user_door(argp, arg_size,
+ dp, _whoami);
+ lookup(argp, arg_size);
+
+ break;
+
+ case NSCD_SETENT:
+
+ APP_check_cred(argp, &ent_pid, "NSCD_SETENT");
+ if (NSCD_STATUS_IS_OK(phdr)) {
+ if_selfcred_return_per_user_door(argp, arg_size,
+ dp, _whoami);
+ nss_psetent(argp, arg_size, ent_pid);
+ }
+ break;
+
+ case NSCD_GETENT:
+
+ getent(argp, arg_size);
+ break;
+
+ case NSCD_ENDENT:
+
+ nss_pendent(argp, arg_size);
+ break;
+
+ case NSCD_PUT:
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "door call NSCD_PUT not supported yet\n");
+
+ NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
+ break;
+
+ case NSCD_GETHINTS:
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "door call NSCD_GETHINTS not supported yet\n");
+
+ NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
+ break;
+
+ default:
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "Unknown name service door call op %x\n",
+ phdr->nsc_callnumber);
+
+ NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
+ break;
+ }
+
+ (void) door_return(argp, arg_size, NULL, 0);
+ }
+
+ iam = NSCD_MAIN;
+ callnum = phdr->nsc_callnumber & ~NSCD_WHOAMI;
+ if (callnum == NSCD_IMHERE ||
+ callnum == NSCD_PULSE || callnum == NSCD_FORK)
+ iam = phdr->nsc_callnumber & NSCD_WHOAMI;
+ else
+ callnum = phdr->nsc_callnumber;
+
+ /* nscd -> nscd v2 calls */
+ switch (callnum) {
+
+ case NSCD_PING:
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ break;
+
+ case NSCD_IMHERE:
+ _nscd_proc_iamhere(argp, dp, n_desc, iam);
+ break;
+
+ case NSCD_PULSE:
+ N2N_check_priv(argp, "NSCD_PULSE");
+ if (NSCD_STATUS_IS_OK(phdr))
+ _nscd_proc_pulse(argp, iam);
+ break;
+
+ case NSCD_FORK:
+ N2N_check_priv(argp, "NSCD_FORK");
+ if (NSCD_STATUS_IS_OK(phdr))
+ _nscd_proc_fork(argp, iam);
+ break;
+
+ case NSCD_KILL:
+ N2N_check_priv(argp, "NSCD_KILL");
+ if (NSCD_STATUS_IS_OK(phdr))
+ exit(0);
+ break;
+
+ case NSCD_REFRESH:
+ if (_nscd_refresh() != NSCD_SUCCESS)
+ exit(1);
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ break;
+
+ case NSCD_GETPUADMIN:
+
+ if (_nscd_is_self_cred_on(0, NULL)) {
+ _nscd_peruser_getadmin(argp, sizeof (nscd_admin_t));
+ } else {
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NOT_CONFIGURED);
+ }
+ break;
+
+ case NSCD_GETADMIN:
+
+ len = _nscd_door_getadmin((void *)argp);
+ if (len == 0)
+ break;
+
+ /* size of door buffer not big enough, allocate one */
+ NSCD_ALLOC_DOORBUF(NSCD_GETADMIN, len, uptr, buflen);
+
+ /* copy packed header */
+ *(nss_pheader_t *)uptr = *(nss_pheader_t *)((void *)argp);
+
+ /* set new buffer size */
+ ((nss_pheader_t *)uptr)->pbufsiz = buflen;
+
+ /* try one more time */
+ (void) _nscd_door_getadmin((void *)uptr);
+ (void) door_return(uptr, buflen, NULL, 0);
+ break;
+
+ case NSCD_SETADMIN:
+ N2N_check_priv(argp, "NSCD_SETADMIN");
+ if (NSCD_STATUS_IS_OK(phdr))
+ _nscd_door_setadmin(argp);
+ break;
+
+ case NSCD_KILLSERVER:
+ N2N_check_priv(argp, "NSCD_KILLSERVER");
+ if (NSCD_STATUS_IS_OK(phdr)) {
+ /* also kill the forker nscd if one is running */
+ _nscd_kill_forker();
+ exit(0);
+ }
+ break;
+
+ default:
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "Unknown name service door call op %d\n",
+ phdr->nsc_callnumber);
+
+ NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
+
+ (void) door_return(argp, arg_size, NULL, 0);
+ break;
+
+ }
+ (void) door_return(argp, arg_size, NULL, 0);
+}
+
+int
+_nscd_setup_server(char *execname, char **argv)
+{
+
+ int fd;
+ int errnum;
+ int bind_failed = 0;
+ struct stat buf;
+ sigset_t myset;
+ struct sigaction action;
+ char *me = "_nscd_setup_server";
+
+ main_execname = execname;
+ main_argv = argv;
+
+ keep_open_dns_socket();
+
+ /*
+ * the max number of server threads should be fixed now, so
+ * set flag to indicate that no in-flight change is allowed
+ */
+ max_servers_set = 1;
+
+ (void) thr_keycreate(&lookup_state_key, NULL);
+ (void) sema_init(&common_sema,
+ frontend_cfg_g.common_worker_threads,
+ USYNC_THREAD, 0);
+
+ /* Establish server thread pool */
+ (void) door_server_create(server_create);
+ if (thr_keycreate(&server_key, server_destroy) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_keycreate (server thread): %s\n",
+ strerror(errnum));
+ return (-1);
+ }
+
+ /* Create a door */
+ if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE,
+ DOOR_UNREF | DOOR_NO_CANCEL)) < 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "door_create: %s\n", strerror(errnum));
+ return (-1);
+ }
+
+ /* if not main nscd, no more setup to do */
+ if (_whoami != NSCD_MAIN)
+ return (fd);
+
+ /* bind to file system */
+ if (is_system_labeled()) {
+ if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) {
+ int newfd;
+ if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "Cannot create %s: %s\n",
+ TSOL_NAME_SERVICE_DOOR,
+ strerror(errnum));
+ bind_failed = 1;
+ }
+ (void) close(newfd);
+ }
+ if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) {
+ if (errno != EEXIST) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "Cannot symlink %s: %s\n",
+ NAME_SERVICE_DOOR,
+ strerror(errnum));
+ bind_failed = 1;
+ }
+ }
+ } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
+ int newfd;
+ if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "Cannot create %s: %s\n", NAME_SERVICE_DOOR,
+ strerror(errnum));
+ bind_failed = 1;
+ }
+ (void) close(newfd);
+ }
+
+ if (bind_failed == 1) {
+ (void) door_revoke(fd);
+ return (-1);
+ }
+
+ if (fattach(fd, NAME_SERVICE_DOOR) < 0) {
+ if ((errno != EBUSY) ||
+ (fdetach(NAME_SERVICE_DOOR) < 0) ||
+ (fattach(fd, NAME_SERVICE_DOOR) < 0)) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "fattach: %s\n", strerror(errnum));
+ (void) door_revoke(fd);
+ return (-1);
+ }
+ }
+
+ /*
+ * kick off routing socket monitor thread
+ */
+ if (thr_create(NULL, NULL,
+ (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create (routing socket monitor): %s\n",
+ strerror(errnum));
+
+ (void) door_revoke(fd);
+ return (-1);
+ }
+
+ /*
+ * set up signal handler for SIGHUP
+ */
+ action.sa_handler = dozip;
+ action.sa_flags = 0;
+ (void) sigemptyset(&action.sa_mask);
+ (void) sigemptyset(&myset);
+ (void) sigaddset(&myset, SIGHUP);
+
+ if (sigaction(SIGHUP, &action, NULL) < 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "sigaction (SIGHUP): %s\n", strerror(errnum));
+
+ (void) door_revoke(fd);
+ return (-1);
+ }
+
+ return (fd);
+}
+
+int
+_nscd_setup_child_server(int did)
+{
+
+ int errnum;
+ int fd;
+ nscd_rc_t rc;
+ char *me = "_nscd_setup_child_server";
+
+ /* Re-establish our own server thread pool */
+ (void) door_server_create(server_create);
+ if (thr_keycreate(&server_key, server_destroy) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "thr_keycreate failed: %s", strerror(errnum));
+ return (-1);
+ }
+
+ /*
+ * Create a new door.
+ * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork)
+ */
+ (void) close(did);
+ if ((fd = door_create(switcher,
+ NAME_SERVICE_DOOR_COOKIE,
+ DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_create failed: %s", strerror(errnum));
+ return (-1);
+ }
+
+ /*
+ * kick off routing socket monitor thread
+ */
+ if (thr_create(NULL, NULL,
+ (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create (routing socket monitor): %s\n",
+ strerror(errnum));
+ (void) door_revoke(fd);
+ return (-1);
+ }
+
+ /*
+ * start monitoring the states of the name service clients
+ */
+ rc = _nscd_init_smf_monitor();
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to start the SMF monitor (rc = %d)\n", rc);
+
+ (void) door_revoke(fd);
+ return (-1);
+ }
+
+ return (fd);
+}
+
+nscd_rc_t
+_nscd_alloc_frontend_cfg()
+{
+ frontend_cfg = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_frontend_t));
+ if (frontend_cfg == NULL)
+ return (NSCD_NO_MEMORY);
+
+ return (NSCD_SUCCESS);
+}
+
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_frontend_notify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void *cookie)
+{
+ void *dp;
+
+ /*
+ * At init time, the whole group of config params are received.
+ * At update time, group or individual parameter value could
+ * be received.
+ */
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
+ _nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+ /*
+ * group data is received, copy in the
+ * entire strcture
+ */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL))
+ frontend_cfg_g =
+ *(nscd_cfg_global_frontend_t *)data;
+ else
+ frontend_cfg[nswdb->index] =
+ *(nscd_cfg_frontend_t *)data;
+
+ } else {
+ /*
+ * individual paramater is received: copy in the
+ * parameter value.
+ */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL))
+ dp = (char *)&frontend_cfg_g + pdesc->p_offset;
+ else
+ dp = (char *)&frontend_cfg[nswdb->index] +
+ pdesc->p_offset;
+ (void) memcpy(dp, data, pdesc->p_size);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_frontend_verify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+
+ char *me = "_nscd_cfg_frontend_verify";
+
+ /*
+ * if max. number of server threads is set and in effect,
+ * don't allow changing of the frontend configuration
+ */
+ if (max_servers_set) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO)
+ (me, "changing of the frontend configuration not allowed now");
+
+ return (NSCD_CFG_CHANGE_NOT_ALLOWED);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_frontend_get_stat(
+ void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)(void *stat),
+ nscd_cfg_error_t **errorp)
+{
+ return (NSCD_SUCCESS);
+}
+
+void
+_nscd_init_cache_sema(sema_t *sema, char *cache_name)
+{
+ int i, j;
+ char *dbn;
+
+ if (max_servers == 0)
+ max_servers = frontend_cfg_g.common_worker_threads +
+ frontend_cfg_g.cache_hit_threads;
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ dbn = NSCD_NSW_DB_NAME(i);
+ if (strcasecmp(dbn, cache_name) == 0) {
+ j = frontend_cfg[i].worker_thread_per_nsw_db;
+ (void) sema_init(sema, j, USYNC_THREAD, 0);
+ max_servers += j;
+ break;
+ }
+ }
+}
+
+/*
+ * Monitor the routing socket. Address lists stored in the ipnodes
+ * cache are sorted based on destination address selection rules,
+ * so when things change that could affect that sorting (interfaces
+ * go up or down, flags change, etc.), we clear that cache so the
+ * list will be re-ordered the next time the hostname is resolved.
+ */
+static void
+rts_mon(void)
+{
+ int rt_sock, rdlen, idx;
+ union {
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_storage addrs[RTA_NUMBITS];
+ } r;
+ struct if_msghdr ifm;
+ struct ifa_msghdr ifam;
+ } mbuf;
+ struct ifa_msghdr *ifam = &mbuf.ifam;
+ char *me = "rts_mon";
+
+ rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (rt_sock < 0) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "Failed to open routing socket: %s\n", strerror(errno));
+ thr_exit(0);
+ }
+
+ for (;;) {
+ rdlen = read(rt_sock, &mbuf, sizeof (mbuf));
+ if (rdlen <= 0) {
+ if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "routing socket read: %s\n",
+ strerror(errno));
+ thr_exit(0);
+ }
+ continue;
+ }
+ if (ifam->ifam_version != RTM_VERSION) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "rx unknown version (%d) on "
+ "routing socket.\n",
+ ifam->ifam_version);
+ continue;
+ }
+ switch (ifam->ifam_type) {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ /* if no ipnodes cache, then nothing to do */
+ idx = get_cache_idx("ipnodes");
+ if (cache_ctx_p[idx] == NULL ||
+ cache_ctx_p[idx]->reaper_on != nscd_true)
+ break;
+ nsc_invalidate(cache_ctx_p[idx], NULL, NULL);
+ break;
+ case RTM_ADD:
+ case RTM_DELETE:
+ case RTM_CHANGE:
+ case RTM_GET:
+ case RTM_LOSING:
+ case RTM_REDIRECT:
+ case RTM_MISS:
+ case RTM_LOCK:
+ case RTM_OLDADD:
+ case RTM_OLDDEL:
+ case RTM_RESOLVE:
+ case RTM_IFINFO:
+ break;
+ default:
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "rx unknown msg type (%d) on routing socket.\n",
+ ifam->ifam_type);
+ break;
+ }
+ }
+}
+
+static void
+keep_open_dns_socket(void)
+{
+ _res.options |= RES_STAYOPEN; /* just keep this udp socket open */
+}
diff --git a/usr/src/cmd/nscd/nscd_frontend.h b/usr/src/cmd/nscd/nscd_frontend.h
new file mode 100644
index 0000000000..73c0fa1d68
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_frontend.h
@@ -0,0 +1,84 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_FRONTEND_H
+#define _NSCD_FRONTEND_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cache.h"
+
+#define NSCD_LOOKUP_BUFSIZE 1024 * 16
+#define NSCD_DOORBUF_MAXLEN 1024 * 512
+#define NSCD_PHDR_LEN(hdrp) ((hdrp)->data_off)
+#define NSCD_DATA_LEN(hdrp) ((hdrp)->data_len)
+
+#define NSCD_ALLOC_LOOKUP_BUFFER(bufp, bufsiz, hdrp, space, spsiz) \
+ if ((hdrp)->pbufsiz <= spsiz) { \
+ (void) memcpy(space, (hdrp), NSCD_PHDR_LEN((hdrp))); \
+ bufp = space; \
+ bufsiz = spsiz; \
+ hdrp = (nss_pheader_t *)(void *)space; \
+ } else { \
+ (bufp) = NULL; \
+ bufsiz = (hdrp)->pbufsiz; \
+ if (bufsiz > spsiz) \
+ bufsiz = NSCD_DOORBUF_MAXLEN; \
+ (bufp) = alloca(bufsiz); \
+ if ((bufp) != NULL) { \
+ (void) memcpy((bufp), (hdrp), NSCD_PHDR_LEN(hdrp)); \
+ (hdrp) = (nss_pheader_t *)(void *)(bufp); \
+ } else { \
+ NSCD_SET_STATUS((hdrp), NSS_ERROR, ENOMEM); \
+ (void) door_return((char *)(hdrp), \
+ NSCD_PHDR_LEN(hdrp), NULL, 0); \
+ } \
+ }
+
+#define NSCD_SET_RETURN_ARG(hdrp, arg_size) \
+ if (NSCD_STATUS_IS_OK((nss_pheader_t *)(hdrp))) \
+ arg_size = NSCD_PHDR_LEN(hdrp) + (NSCD_DATA_LEN(hdrp) > 0 ? \
+ NSCD_DATA_LEN(hdrp) + 1 : 0); \
+ else \
+ arg_size = NSCD_PHDR_LEN(hdrp);
+
+/* prototypes */
+uid_t _nscd_get_client_euid();
+int _nscd_setup_server(char *execname, char **argv);
+int _nscd_setup_child_server(int did);
+int _nscd_get_clearance(sema_t *sema);
+int _nscd_release_clearance(sema_t *sema);
+void _nscd_init_cache_sema(sema_t *sema, char *cache_name);
+nscd_rc_t _nscd_alloc_frontend_cfg();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_FRONTEND_H */
diff --git a/usr/src/cmd/nscd/nscd_getentctx.c b/usr/src/cmd/nscd/nscd_getentctx.c
new file mode 100644
index 0000000000..d37b8d1cf3
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_getentctx.c
@@ -0,0 +1,661 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "nscd_db.h"
+#include "nscd_log.h"
+#include "nscd_switch.h"
+#include "nscd_door.h"
+
+extern int _whoami;
+static mutex_t getent_monitor_mutex = DEFAULTMUTEX;
+static int getent_monitor_started = 0;
+
+static rwlock_t getent_ctxDB_rwlock = DEFAULTRWLOCK;
+static nscd_db_t *getent_ctxDB = NULL;
+
+/*
+ * internal structure representing a nscd getent context
+ */
+typedef struct nscd_getent_ctx {
+ int to_delete; /* this ctx no longer valid */
+ nscd_getent_context_t *ptr;
+ nscd_cookie_t cookie;
+} nscd_getent_ctx_t;
+
+/*
+ * nscd_getent_context_t list for each nss database. Protected
+ * by the readers/writer lock nscd_getent_ctx_lock.
+ */
+nscd_getent_ctx_base_t **nscd_getent_ctx_base;
+static rwlock_t nscd_getent_ctx_base_lock = DEFAULTRWLOCK;
+
+extern nscd_db_entry_t *_nscd_walk_db(nscd_db_t *db, void **cookie);
+
+static nscd_rc_t _nscd_init_getent_ctx_monitor();
+
+/*
+ * FUNCTION: _nscd_create_getent_ctxDB
+ *
+ * Create the internal getent context database to keep track of the
+ * getent contexts currently being used.
+ */
+nscd_db_t *
+_nscd_create_getent_ctxDB()
+{
+
+ nscd_db_t *ret;
+
+ (void) rw_wrlock(&getent_ctxDB_rwlock);
+
+ if (getent_ctxDB != NULL) {
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+ return (getent_ctxDB);
+ }
+
+ ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE);
+
+ if (ret != NULL)
+ getent_ctxDB = ret;
+
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_add_getent_ctx
+ *
+ * Add a getent context to the internal context database.
+ */
+static nscd_rc_t
+_nscd_add_getent_ctx(
+ nscd_getent_context_t *ptr,
+ nscd_cookie_t cookie)
+{
+ int size;
+ char buf[2 * sizeof (cookie) + 1];
+ nscd_db_entry_t *db_entry;
+ nscd_getent_ctx_t *gnctx;
+
+ if (ptr == NULL)
+ return (NSCD_INVALID_ARGUMENT);
+
+ (void) snprintf(buf, sizeof (buf), "%lld", cookie);
+
+ size = sizeof (*gnctx);
+
+ db_entry = _nscd_alloc_db_entry(NSCD_DATA_CTX_ADDR,
+ (const char *)buf, size, 1, 1);
+ if (db_entry == NULL)
+ return (NSCD_NO_MEMORY);
+
+ gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
+ gnctx->ptr = ptr;
+ gnctx->cookie = cookie;
+
+ (void) rw_wrlock(&getent_ctxDB_rwlock);
+ (void) _nscd_add_db_entry(getent_ctxDB, buf, db_entry,
+ NSCD_ADD_DB_ENTRY_FIRST);
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * FUNCTION: _nscd_is_getent_ctx
+ *
+ * Check to see if a getent context can be found in the internal
+ * getent context database.
+ */
+nscd_getent_context_t *
+_nscd_is_getent_ctx(
+ nscd_cookie_t cookie)
+{
+ char ptrstr[1 + 2 * sizeof (cookie)];
+ const nscd_db_entry_t *db_entry;
+ nscd_getent_context_t *ret = NULL;
+
+ (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie);
+
+ (void) rw_rdlock(&getent_ctxDB_rwlock);
+
+ db_entry = _nscd_get_db_entry(getent_ctxDB, NSCD_DATA_CTX_ADDR,
+ (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0);
+
+ if (db_entry != NULL) {
+ nscd_getent_ctx_t *gnctx;
+
+ gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
+
+ /*
+ * If the ctx is not to be deleted and
+ * the cookie numbers match, return the ctx.
+ * Otherwise return NULL.
+ */
+ if (gnctx->to_delete == 0 && gnctx->cookie == cookie)
+ ret = gnctx->ptr;
+ }
+
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_del_getent_ctx
+ *
+ * Delete a getent context from the internal getent context database.
+ */
+static void
+_nscd_del_getent_ctx(
+ nscd_getent_context_t *ptr,
+ nscd_cookie_t cookie)
+{
+ char ptrstr[1 + 2 * sizeof (cookie)];
+ nscd_getent_ctx_t *gnctx;
+ const nscd_db_entry_t *db_entry;
+
+ if (ptr == NULL)
+ return;
+
+ (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie);
+
+ (void) rw_rdlock(&getent_ctxDB_rwlock);
+ /*
+ * first find the db entry and make sure the
+ * sequence number matched, then delete it from
+ * the database.
+ */
+ db_entry = _nscd_get_db_entry(getent_ctxDB,
+ NSCD_DATA_CTX_ADDR,
+ (const char *)ptrstr,
+ NSCD_GET_FIRST_DB_ENTRY, 0);
+ if (db_entry != NULL) {
+ gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
+ if (gnctx->ptr == ptr && gnctx->cookie == cookie) {
+
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+ (void) rw_wrlock(&getent_ctxDB_rwlock);
+
+ (void) _nscd_delete_db_entry(getent_ctxDB,
+ NSCD_DATA_CTX_ADDR,
+ (const char *)ptrstr,
+ NSCD_DEL_FIRST_DB_ENTRY, 0);
+ }
+ }
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+}
+
+static void
+_nscd_free_getent_ctx(
+ nscd_getent_context_t *gnctx)
+{
+
+ char *me = "_nscd_free_getent_ctx";
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getent context %p\n", gnctx);
+
+ _nscd_put_nsw_state(gnctx->nsw_state);
+ _nscd_del_getent_ctx(gnctx, gnctx->cookie);
+ free(gnctx);
+}
+
+
+static void
+_nscd_free_getent_ctx_base(
+ nscd_acc_data_t *data)
+{
+ nscd_getent_ctx_base_t *base = (nscd_getent_ctx_base_t *)data;
+ nscd_getent_context_t *c, *tc;
+ char *me = "_nscd_free_getent_ctx_base";
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getent context base %p\n", base);
+
+ if (base == NULL)
+ return;
+
+ c = base->first;
+ while (c != NULL) {
+ tc = c->next;
+ _nscd_free_getent_ctx(c);
+ c = tc;
+ }
+}
+
+void
+_nscd_free_all_getent_ctx_base()
+{
+ nscd_getent_ctx_base_t *base;
+ int i;
+ char *me = "_nscd_free_all_getent_ctx_base";
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "entering ..\n");
+
+ (void) rw_wrlock(&nscd_getent_ctx_base_lock);
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ base = nscd_getent_ctx_base[i];
+ if (base == NULL)
+ continue;
+
+ nscd_getent_ctx_base[i] = (nscd_getent_ctx_base_t *)
+ _nscd_set((nscd_acc_data_t *)base, NULL);
+ }
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+}
+
+static nscd_getent_context_t *
+_nscd_create_getent_ctx(
+ nscd_nsw_params_t *params)
+{
+ nscd_getent_context_t *gnctx;
+ nss_db_root_t db_root;
+ char *me = "_nscd_create_getent_ctx";
+
+ gnctx = calloc(1, sizeof (nscd_getent_context_t));
+ if (gnctx == NULL)
+ return (NULL);
+ else {
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getent context allocated %p\n", gnctx);
+ }
+
+ gnctx->dbi = params->dbi;
+ gnctx->cookie = _nscd_get_cookie();
+
+ if (_nscd_get_nsw_state(&db_root, params) != NSCD_SUCCESS) {
+ free(gnctx);
+ return (NULL);
+ }
+ gnctx->nsw_state = (nscd_nsw_state_t *)db_root.s;
+ /* this is a nsw_state used for getent processing */
+ gnctx->nsw_state->getent = 1;
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got nsw_state %p\n", gnctx->nsw_state);
+
+ return (gnctx);
+}
+
+
+nscd_rc_t
+_nscd_get_getent_ctx(
+ nss_getent_t *contextpp,
+ nscd_nsw_params_t *params)
+{
+
+ nscd_getent_context_t *c;
+ nscd_getent_ctx_base_t *base, *tmp;
+ nscd_rc_t rc;
+ char *me = "_nscd_get_getent_ctx";
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "entering ...\n");
+
+ (void) rw_rdlock(&nscd_getent_ctx_base_lock);
+ base = nscd_getent_ctx_base[params->dbi];
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+ assert(base != NULL);
+
+ /*
+ * If the context list is not empty, return the first one
+ * on the list. Otherwise, create and return a new one if
+ * limit is not reached. if reacehed, wait for the 'one is
+ * available' signal.
+ */
+ tmp = (nscd_getent_ctx_base_t *)_nscd_mutex_lock(
+ (nscd_acc_data_t *)base);
+ assert(base == tmp);
+ if (base->first == NULL) {
+ if (base->num_getent_ctx == base->max_getent_ctx) {
+ base->num_waiter++;
+ while (base->first == NULL) {
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "waiting for signal\n");
+
+ _nscd_cond_wait((nscd_acc_data_t *)base, NULL);
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "woke up\n");
+ }
+ base->num_waiter--;
+ } else {
+ base->first = _nscd_create_getent_ctx(params);
+ if (base->first != NULL) {
+ base->first->base = base;
+ base->num_getent_ctx++;
+ } else {
+ /* not able to create an getent ctx */
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "create getent ctx failed\n");
+
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+ return (NSCD_CREATE_GETENT_CTX_FAILED);
+ }
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got a new getent ctx %p\n", base->first);
+ }
+ }
+
+ assert(base->first != NULL);
+
+ c = base->first;
+ base->first = c->next;
+ c->next = NULL;
+ c->seq_num = 1;
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got a getent ctx %p\n", c);
+
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "adding new ctx %p, cookie = %lld\n", c, c->cookie);
+
+ if ((rc = _nscd_add_getent_ctx(c, c->cookie)) != NSCD_SUCCESS) {
+ _nscd_put_getent_ctx(c);
+ return (rc);
+ }
+ contextpp->ctx = (struct nss_getent_context *)c;
+
+ /* start monitor and reclaim orphan getent context */
+ if (getent_monitor_started == 0) {
+ (void) mutex_lock(&getent_monitor_mutex);
+ if (getent_monitor_started == 0) {
+ getent_monitor_started = 1;
+ (void) _nscd_init_getent_ctx_monitor();
+ }
+ (void) mutex_unlock(&getent_monitor_mutex);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+void
+_nscd_put_getent_ctx(
+ nscd_getent_context_t *gnctx)
+{
+
+ nscd_getent_ctx_base_t *base;
+ char *me = "_nscd_put_getent_ctx";
+
+ base = gnctx->base;
+ gnctx->seq_num = 0;
+
+ /* if context base is gone, so should this context */
+ if ((_nscd_mutex_lock((nscd_acc_data_t *)base)) == NULL) {
+ _nscd_free_getent_ctx(gnctx);
+ return;
+ }
+
+ if (base->first != NULL) {
+ gnctx->next = base->first;
+ base->first = gnctx;
+ } else
+ base->first = gnctx;
+
+ /* put back the db state */
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "putting back nsw state %p\n", gnctx->nsw_state);
+
+ /* this nsw_state is no longer used for getent processing */
+ if (gnctx->nsw_state != NULL)
+ gnctx->nsw_state->getent = 0;
+ _nscd_put_nsw_state(gnctx->nsw_state);
+ gnctx->nsw_state = NULL;
+
+ _nscd_del_getent_ctx(gnctx, gnctx->cookie);
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "ctx (%p seq# = %lld) removed from getent ctx DB\n",
+ gnctx, gnctx->cookie);
+
+ if (base->num_waiter > 0) {
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "signaling (waiter = %d)\n", base->num_waiter);
+
+ _nscd_cond_signal((nscd_acc_data_t *)base);
+ }
+
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+}
+
+nscd_rc_t
+_nscd_init_getent_ctx_base(
+ int dbi,
+ int lock)
+{
+ nscd_getent_ctx_base_t *base = NULL;
+ char *me = "_nscd_init_getent_ctx_base";
+
+ if (lock)
+ (void) rw_rdlock(&nscd_getent_ctx_base_lock);
+
+ base = (nscd_getent_ctx_base_t *)_nscd_alloc(
+ NSCD_DATA_GETENT_CTX_BASE,
+ sizeof (nscd_getent_ctx_base_t),
+ _nscd_free_getent_ctx_base,
+ NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
+
+ if (base == NULL) {
+ if (lock)
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+ return (NSCD_NO_MEMORY);
+ }
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "base %p allocated\n", base);
+
+ /*
+ * initialize and activate the new getent_ctx base
+ */
+ base->dbi = dbi;
+ base->max_getent_ctx = NSCD_SW_CFG(dbi).max_getent_ctx_per_db;
+ nscd_getent_ctx_base[dbi] =
+ (nscd_getent_ctx_base_t *)_nscd_set(
+ (nscd_acc_data_t *)nscd_getent_ctx_base[dbi],
+ (nscd_acc_data_t *)base);
+
+ if (lock)
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_init_all_getent_ctx_base()
+{
+ int i;
+ nscd_rc_t rc;
+ char *me = "_nscd_init_all_getent_ctx_base";
+
+ (void) rw_wrlock(&nscd_getent_ctx_base_lock);
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ rc = _nscd_init_getent_ctx_base(i, 0);
+
+ if (rc != NSCD_SUCCESS) {
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+ return (rc);
+ }
+ }
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "all getent context base initialized\n");
+
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+
+ return (NSCD_SUCCESS);
+}
+nscd_rc_t
+_nscd_alloc_getent_ctx_base()
+{
+
+ (void) rw_wrlock(&nscd_getent_ctx_base_lock);
+
+ nscd_getent_ctx_base = calloc(NSCD_NUM_DB,
+ sizeof (nscd_getent_ctx_base_t *));
+ if (nscd_getent_ctx_base == NULL) {
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+ return (NSCD_NO_MEMORY);
+ }
+
+ (void) rw_unlock(&nscd_getent_ctx_base_lock);
+
+ return (NSCD_SUCCESS);
+}
+
+static int
+process_exited(pid_t pid)
+{
+ char pname[PATH_MAX];
+ int fd;
+
+ (void) snprintf(pname, sizeof (pname), "/proc/%d/psinfo", pid);
+ if ((fd = open(pname, O_RDONLY)) == -1)
+ return (1);
+ else {
+ (void) close(fd);
+ return (0);
+ }
+}
+
+/*
+ * FUNCTION: reclaim_getent_ctx
+ */
+/*ARGSUSED*/
+static void *
+reclaim_getent_ctx(void *arg)
+{
+ void *cookie = NULL;
+ nscd_db_entry_t *ep;
+ nscd_getent_ctx_t *ctx;
+ nscd_getent_context_t *gctx, *c;
+ nscd_getent_context_t *first = NULL, *last = NULL;
+ char *me = "reclaim_getent_ctx";
+
+ /*CONSTCOND*/
+ while (1) {
+
+ (void) rw_rdlock(&getent_ctxDB_rwlock);
+
+ for (ep = _nscd_walk_db(getent_ctxDB, &cookie); ep != NULL;
+ ep = _nscd_walk_db(getent_ctxDB, &cookie)) {
+
+ ctx = (nscd_getent_ctx_t *)*(ep->data_array);
+
+ gctx = ctx->ptr;
+
+ /*
+ * if the client process, which did the setent,
+ * exited, add the context to the orphan list
+ */
+ if (gctx->pid != -1 && process_exited(gctx->pid)) {
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "process %d exited, "
+ "getent context = %p, "
+ "db index = %d, cookie = %lld, "
+ "sequence # = %lld\n",
+ gctx->pid, gctx, gctx->dbi,
+ gctx->cookie, gctx->seq_num);
+
+ if (first != NULL) {
+ last->next = gctx;
+ last = gctx;
+ } else {
+ first = gctx;
+ last = gctx;
+ }
+ }
+ }
+
+ (void) rw_unlock(&getent_ctxDB_rwlock);
+
+
+ /*
+ * return all the orphan getent contexts to the pool
+ */
+ for (gctx = first; gctx; ) {
+ c = gctx->next;
+ gctx->next = NULL;
+ _nscd_put_getent_ctx(gctx);
+ gctx = c;
+ }
+ first = last = NULL;
+
+ (void) sleep(60);
+ }
+ /*NOTREACHED*/
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
+}
+
+static nscd_rc_t
+_nscd_init_getent_ctx_monitor() {
+
+ int errnum;
+ char *me = "_nscd_init_getent_ctx_monitor";
+
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing the getent context monitor\n");
+
+ /*
+ * the forker nscd does not process getent requests
+ * so no need to monitor orphan getent contexts
+ */
+ if (_whoami == NSCD_FORKER)
+ return (NSCD_SUCCESS);
+
+ /*
+ * start a thread to reclaim unused getent contexts
+ */
+ if (thr_create(NULL, NULL, reclaim_getent_ctx,
+ NULL, THR_DETACHED, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create: %s\n", strerror(errnum));
+ return (NSCD_THREAD_CREATE_ERROR);
+ }
+
+ return (NSCD_SUCCESS);
+}
diff --git a/usr/src/cmd/nscd/nscd_init.c b/usr/src/cmd/nscd/nscd_init.c
new file mode 100644
index 0000000000..991d31a9ff
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_init.c
@@ -0,0 +1,241 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <locale.h>
+#include <unistd.h>
+#include <string.h>
+#include "nscd_common.h"
+#include "nscd_config.h"
+#include "nscd_log.h"
+#include "nscd_switch.h"
+#include "nscd_frontend.h"
+
+static char *cfgfile_save = NULL;
+
+nscd_rc_t
+_nscd_init(
+ char *cfgfile)
+{
+ char *me = "nscd_init";
+ nscd_rc_t rc;
+ nscd_cfg_error_t *err;
+
+ /*
+ * allocate the space for tables
+ */
+ rc = _nscd_alloc_nsw_config();
+ rc = _nscd_alloc_service_state_table();
+ rc = _nscd_alloc_nsw_state_base();
+ rc = _nscd_alloc_nsw_be_info_db();
+ rc = _nscd_alloc_getent_ctx_base();
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ /*
+ * allocate the space for local configuration
+ * and statistics
+ */
+ rc = _nscd_alloc_switch_cfg();
+ rc = _nscd_alloc_frontend_cfg();
+ rc = _nscd_alloc_switch_stats();
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ /*
+ * Create and init the internal address database to keep
+ * track of the memory allocated by _nscd_alloc
+ */
+ if (_nscd_create_int_addrDB() == NULL) {
+ _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_ERROR)
+ (me, "_nscd_create_int_addrDB failed\n");
+ return (NSCD_NO_MEMORY);
+ }
+
+ /*
+ * Create and init the internal context database to keep
+ * track of the getent context currently being used
+ */
+ if (_nscd_create_getent_ctxDB() == NULL) {
+ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
+ (me, "_nscd_create_getent_ctx_addrDB failed\n");
+ return (NSCD_NO_MEMORY);
+ }
+
+ /*
+ * Create the backend info database for each possible source
+ */
+ if ((rc = _nscd_init_all_nsw_be_info_db()) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "_nscd_init_all_nsw_be_info_db failed (rc = %d)\n",
+ rc);
+ return (rc);
+ }
+
+ /*
+ * Create the nscd_nsw_config_t for each possible nss database
+ */
+ if ((rc = _nscd_init_all_nsw_config()) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "_nscd_init_all_nsw_config failed (rc = %d)\n", rc);
+ return (rc);
+ }
+
+ /*
+ * populate the backend info databases
+ */
+ if ((rc = _nscd_populate_nsw_backend_info()) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "_nscd_init_all_nsw_be_info_db failed (rc = %d)\n", rc);
+ return (rc);
+ }
+
+ /*
+ * initialize config/stats management
+ */
+ rc = _nscd_cfg_init(&err);
+ if (rc != NSCD_SUCCESS) {
+ if (err != NULL)
+ _nscd_cfg_free_error(err);
+ return (rc);
+ }
+
+ /*
+ * read in the nsswitch configuration
+ */
+ rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err);
+ if (rc != NSCD_SUCCESS) {
+ (void) printf(
+ gettext("reading config file %s failed with rc = %d, %s\n"),
+ "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err));
+ if (err != NULL)
+ _nscd_cfg_free_error(err);
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to read /etc/nsswitch.conf (rc = %d)\n", rc);
+ return (rc);
+ }
+
+ /*
+ * read in the nscd configuration
+ */
+ if (cfgfile == NULL) {
+ cfgfile = "/etc/nscd.conf";
+ if (access(cfgfile, R_OK) != 0) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to read /etc/nscd.conf (rc = %d)\n", rc);
+
+ return (NSCD_CFG_FILE_ACCESS_ERROR);
+ }
+ }
+ rc = _nscd_cfg_read_file(cfgfile, &err);
+ if (rc != NSCD_SUCCESS) {
+ (void) printf(
+ gettext("reading config file %s failed with rc = %d, %s\n"),
+ cfgfile, rc, NSCD_ERR2MSG(err));
+ if (err != NULL)
+ _nscd_cfg_free_error(err);
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to read configuration from %s (rc = %d)\n",
+ cfgfile, rc);
+
+ return (rc);
+ }
+ /*
+ * remember the name of the config file
+ * in case refresh is requested later
+ */
+ if (cfgfile != NULL) {
+ cfgfile_save = strdup(cfgfile);
+ if (cfgfile == NULL)
+ return (NSCD_NO_MEMORY);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_refresh()
+{
+ char *me = "nscd_refresh";
+ char *cfgfile;
+ nscd_rc_t rc;
+ nscd_cfg_error_t *err;
+ char errmsg[1024];
+
+ /*
+ * re-read the nsswitch configuration
+ */
+ rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err);
+ if (rc != NSCD_SUCCESS) {
+ (void) snprintf(errmsg, sizeof (errmsg),
+ "unable to parse the config file %s (rc = %d), %s\n",
+ "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err));
+ goto error_exit;
+ }
+
+ /*
+ * re-read the nscd configuration
+ */
+ if (cfgfile_save == NULL)
+ cfgfile = "/etc/nscd.conf";
+ else
+ cfgfile = cfgfile_save;
+
+ if (access(cfgfile, R_OK) != 0) {
+ (void) snprintf(errmsg, sizeof (errmsg),
+ "unable to read the config file %s (rc = %d), %s\n",
+ cfgfile, NSCD_CFG_FILE_ACCESS_ERROR,
+ strerror(errno));
+
+ goto error_exit;
+ }
+
+ rc = _nscd_cfg_read_file(cfgfile, &err);
+ if (rc != NSCD_SUCCESS) {
+ (void) snprintf(errmsg, sizeof (errmsg),
+ "unable to parse the config file %s (rc = %d), %s\n",
+ cfgfile, rc, NSCD_ERR2MSG(err));
+
+ goto error_exit;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ALL)
+ (me, "nsswitch/nscd configuration refreshed successfully\n");
+
+ return (NSCD_SUCCESS);
+
+ error_exit:
+
+ if (err != NULL)
+ _nscd_cfg_free_error(err);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", errmsg);
+
+ return (rc);
+}
diff --git a/usr/src/cmd/nscd/nscd_initf.c b/usr/src/cmd/nscd/nscd_initf.c
new file mode 100644
index 0000000000..e225923907
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_initf.c
@@ -0,0 +1,250 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nss_common.h>
+#include <nss_dbdefs.h>
+#include "nscd_common.h"
+#include "nscd_switch.h"
+
+void
+_nss_initf_passwd(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PASSWD;
+ p->default_config = NSS_DEFCONF_PASSWD;
+}
+
+void
+_nss_initf_hosts(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_HOSTS;
+ p->default_config = NSS_DEFCONF_HOSTS;
+}
+
+void
+_nss_initf_group(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_GROUP;
+ p->default_config = NSS_DEFCONF_GROUP;
+}
+
+void
+_nss_initf_ipnodes(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_IPNODES;
+ p->default_config = NSS_DEFCONF_IPNODES;
+}
+
+void
+_nss_initf_net(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_NETWORKS;
+ p->default_config = NSS_DEFCONF_NETWORKS;
+}
+
+void
+_nss_initf_proto(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PROTOCOLS;
+ p->default_config = NSS_DEFCONF_PROTOCOLS;
+}
+
+void
+_nss_initf_rpc(p)
+ nss_db_params_t *p;
+{
+ p->name = NSS_DBNAM_RPC;
+ p->default_config = NSS_DEFCONF_RPC;
+}
+
+void
+_nss_initf_ethers(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_ETHERS;
+ p->default_config = NSS_DEFCONF_ETHERS;
+}
+
+void
+_nss_initf_netmasks(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_NETMASKS;
+ p->default_config = NSS_DEFCONF_NETMASKS;
+}
+
+void
+_nss_initf_bootparams(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_BOOTPARAMS;
+ p->default_config = NSS_DEFCONF_BOOTPARAMS;
+}
+
+void
+_nss_initf_publickey(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PUBLICKEY;
+ p->default_config = NSS_DEFCONF_PUBLICKEY;
+}
+
+void
+_nss_initf_netgroup(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_NETGROUP;
+ p->default_config = NSS_DEFCONF_NETGROUP;
+}
+
+void
+_nss_initf_services(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_SERVICES;
+ p->default_config = NSS_DEFCONF_SERVICES;
+}
+
+void
+_nss_initf_printers(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PRINTERS;
+ p->default_config = NSS_DEFCONF_PRINTERS;
+}
+
+void
+_nss_initf_authattr(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_AUTHATTR;
+ p->default_config = NSS_DEFCONF_AUTHATTR;
+}
+
+void
+_nss_initf_profattr(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PROFATTR;
+ p->default_config = NSS_DEFCONF_PROFATTR;
+}
+
+void
+_nss_initf_execattr(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_EXECATTR;
+ p->default_config = NSS_DEFCONF_PROFATTR;
+ p->config_name = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
+}
+
+void
+_nss_initf_userattr(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_USERATTR;
+ p->config_name = NSS_DBNAM_PASSWD;
+ p->default_config = NSS_DEFCONF_USERATTR;
+}
+
+void
+_nss_initf_project(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PROJECT;
+ p->default_config = NSS_DEFCONF_PROJECT;
+}
+
+void
+_nss_initf_auuser(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_AUDITUSER;
+ p->config_name = NSS_DBNAM_PASSWD;
+ p->default_config = NSS_DEFCONF_AUDITUSER;
+}
+
+void
+_nss_initf_shadow(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_SHADOW;
+ p->config_name = NSS_DBNAM_PASSWD;
+ p->default_config = NSS_DEFCONF_PASSWD;
+}
+
+void
+_nss_initf_passwd_compat(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_PASSWD;
+ p->config_name = NSS_DBNAM_PASSWD_COMPAT;
+ p->default_config = NSS_DEFCONF_PASSWD_COMPAT;
+}
+
+void
+_nss_initf_group_compat(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_GROUP;
+ p->config_name = NSS_DBNAM_GROUP_COMPAT;
+ p->default_config = NSS_DEFCONF_GROUP_COMPAT;
+}
+
+void
+_nss_initf_tsol_rh(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_TSOL_RH;
+ p->default_config = NSS_DEFCONF_TSOL_RH;
+}
+
+void
+_nss_initf_tsol_tp(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_TSOL_TP;
+ p->default_config = NSS_DEFCONF_TSOL_TP;
+}
+
+nss_db_initf_t nscd_nss_db_initf[] = {
+ _nss_initf_passwd,
+ _nss_initf_hosts,
+ _nss_initf_group,
+ _nss_initf_ipnodes,
+ _nss_initf_net,
+ _nss_initf_proto,
+ _nss_initf_rpc,
+ _nss_initf_ethers,
+ _nss_initf_netmasks,
+ _nss_initf_bootparams,
+ _nss_initf_publickey,
+ _nss_initf_netgroup,
+ _nss_initf_services,
+ _nss_initf_printers,
+ _nss_initf_authattr,
+ _nss_initf_profattr,
+ _nss_initf_execattr,
+ _nss_initf_userattr,
+ _nss_initf_project,
+ _nss_initf_shadow,
+ _nss_initf_auuser,
+ _nss_initf_tsol_rh,
+ _nss_initf_tsol_tp,
+ _nss_initf_passwd_compat,
+ _nss_initf_group_compat,
+ /*
+ * no initf() for pseudo-databases: passwd, shadow,
+ * audit_user, user_attr, and group (when called from
+ * the compat backend)
+ */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL};
diff --git a/usr/src/cmd/nscd/nscd_intaddr.c b/usr/src/cmd/nscd/nscd_intaddr.c
new file mode 100644
index 0000000000..f427d0c98a
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_intaddr.c
@@ -0,0 +1,248 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "nscd_db.h"
+#include "nscd_log.h"
+
+static rwlock_t addrDB_rwlock = DEFAULTRWLOCK;
+static nscd_db_t *addrDB = NULL;
+
+/*
+ * internal structure representing a nscd internal address
+ */
+typedef struct nscd_int_addr {
+ int to_delete; /* no longer valid */
+ int type;
+ void *ptr;
+ nscd_seq_num_t seq_num;
+ rwlock_t rwlock; /* used to serialize get and destroy */
+} nscd_int_addr_t;
+
+/*
+ * FUNCTION: _nscd_create_int_addrDB
+ *
+ * Create the internal address database to keep track of the
+ * memory allocated by _nscd_alloc.
+ */
+void *
+_nscd_create_int_addrDB()
+{
+
+ nscd_db_t *ret;
+ char *me = "_nscd_create_int_addrDB";
+
+ _NSCD_LOG(NSCD_LOG_INT_ADDR | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing the internal address database\n");
+
+ (void) rw_wrlock(&addrDB_rwlock);
+
+ if (addrDB != NULL) {
+ (void) rw_unlock(&addrDB_rwlock);
+ return (addrDB);
+ }
+
+ ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE);
+
+ if (ret != NULL)
+ addrDB = ret;
+
+ (void) rw_unlock(&addrDB_rwlock);
+
+ return (ret);
+}
+
+/*
+ * FUNCTION: _nscd_add_int_addr
+ *
+ * Add an address of 'type' to the internal address database.
+ */
+nscd_rc_t
+_nscd_add_int_addr(
+ void *ptr,
+ int type,
+ nscd_seq_num_t seq_num)
+{
+ int size;
+ char buf[2 * sizeof (ptr) + 1];
+ nscd_db_entry_t *db_entry;
+ nscd_int_addr_t *int_addr;
+
+ if (ptr == NULL)
+ return (NSCD_INVALID_ARGUMENT);
+
+ (void) snprintf(buf, sizeof (buf), "%p", ptr);
+
+ size = sizeof (*int_addr);
+
+ db_entry = _nscd_alloc_db_entry(NSCD_DATA_ADDR,
+ (const char *)buf, size, 1, 1);
+ if (db_entry == NULL)
+ return (NSCD_NO_MEMORY);
+
+ int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
+ int_addr->ptr = ptr;
+ int_addr->type = type;
+ int_addr->seq_num = seq_num;
+ (void) rwlock_init(&int_addr->rwlock, USYNC_THREAD, NULL);
+
+ (void) rw_wrlock(&addrDB_rwlock);
+ (void) _nscd_add_db_entry(addrDB, buf, db_entry,
+ NSCD_ADD_DB_ENTRY_FIRST);
+ (void) rw_unlock(&addrDB_rwlock);
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * FUNCTION: _nscd_is_int_addr
+ *
+ * Check to see if an address can be found in the internal
+ * address database, if so, obtain a reader lock on the
+ * associated rw_lock. The caller needs to unlock it when
+ * done using the data.
+ */
+rwlock_t *
+_nscd_is_int_addr(
+ void *ptr,
+ nscd_seq_num_t seq_num)
+{
+ char *me = "_nscd_is_int_addr";
+ char ptrstr[1 + 2 * sizeof (ptr)];
+ rwlock_t *addr_rwlock;
+ const nscd_db_entry_t *db_entry;
+
+ if (ptr == NULL)
+ return (NULL);
+
+ (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr);
+
+ (void) rw_rdlock(&addrDB_rwlock);
+
+ db_entry = _nscd_get_db_entry(addrDB, NSCD_DATA_ADDR,
+ (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0);
+
+ if (db_entry != NULL) {
+ nscd_int_addr_t *int_addr;
+
+ int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
+ addr_rwlock = &int_addr->rwlock;
+ (void) rw_rdlock(addr_rwlock);
+
+ /*
+ * If the data is marked as to be deleted
+ * or the sequence number does not match,
+ * return NULL.
+ */
+ if (int_addr->to_delete == 1 ||
+ int_addr->seq_num != seq_num) {
+ (void) rw_unlock(addr_rwlock);
+ addr_rwlock = NULL;
+ }
+
+ _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG)
+ (me, "found %p, seq# = %lld\n", ptr, int_addr->seq_num);
+ } else
+ addr_rwlock = NULL;
+
+ (void) rw_unlock(&addrDB_rwlock);
+
+ return (addr_rwlock);
+}
+
+/*
+ * FUNCTION: _nscd_del_int_addr
+ *
+ * Delete an address from the internal address database.
+ */
+void
+_nscd_del_int_addr(
+ void *ptr,
+ nscd_seq_num_t seq_num)
+{
+ char *me = "_nscd_del_int_addr";
+ char ptrstr[1 + 2 * sizeof (ptr)];
+ rwlock_t *addr_rwlock;
+ nscd_int_addr_t *int_addr;
+ const nscd_db_entry_t *db_entry;
+
+ if (ptr == NULL)
+ return;
+
+ _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG)
+ (me, "deleting int addr %p (%d)\n", ptr, seq_num);
+ (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr);
+
+ (void) rw_rdlock(&addrDB_rwlock);
+ /*
+ * first find the db entry and make sure that
+ * no one is currently locking it. i.e.,
+ * no one is waiting to use the same address.
+ * If it is locked, rw_wrlock() will not return
+ * until it is unlocked.
+ */
+ db_entry = _nscd_get_db_entry(addrDB,
+ NSCD_DATA_ADDR,
+ (const char *)ptrstr,
+ NSCD_GET_FIRST_DB_ENTRY, 0);
+ if (db_entry != NULL) {
+ int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
+ addr_rwlock = &int_addr->rwlock;
+ (void) rw_wrlock(addr_rwlock);
+ } else {
+ (void) rw_unlock(&addrDB_rwlock);
+ return;
+ }
+ (void) rw_unlock(&addrDB_rwlock);
+
+ /*
+ * delete the db entry if the sequence numbers match
+ */
+ if (int_addr->seq_num == seq_num) {
+ (void) rw_wrlock(&addrDB_rwlock);
+ (void) _nscd_delete_db_entry(addrDB,
+ NSCD_DATA_ADDR,
+ (const char *)ptrstr,
+ NSCD_DEL_FIRST_DB_ENTRY, 0);
+ (void) rw_unlock(&addrDB_rwlock);
+ }
+}
+
+/*
+ * FUNCTION: _nscd_destroy_int_addrDB
+ *
+ * Destroy the internal address database.
+ */
+void
+_nscd_destroy_int_addrDB()
+{
+ (void) rw_wrlock(&addrDB_rwlock);
+ _nscd_free_db(addrDB);
+ addrDB = NULL;
+ (void) rw_unlock(&addrDB_rwlock);
+}
diff --git a/usr/src/cmd/nscd/nscd_log.c b/usr/src/cmd/nscd/nscd_log.c
new file mode 100644
index 0000000000..748fcb2ddb
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_log.c
@@ -0,0 +1,427 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <locale.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/varargs.h>
+#include <synch.h>
+#include <thread.h>
+#include <string.h>
+#include <unistd.h>
+#include "nscd_log.h"
+#include "nscd_config.h"
+#include "nscd_switch.h"
+#include "cache.h"
+
+/*
+ * old nscd debug levels
+ */
+#define DBG_OFF 0
+#define DBG_CANT_FIND 2
+#define DBG_NETLOOKUPS 4
+#define DBG_ALL 6
+
+/* max. chars in a nscd log entry */
+#define LOGBUFLEN 1024
+
+/* configuration for the nscd log component */
+int _nscd_log_comp = 0x0;
+int _nscd_log_level = 0x0;
+static char logfile[PATH_MAX];
+
+/* statistics data */
+static nscd_cfg_stat_global_log_t logstats = {
+ NSCD_CFG_STAT_GROUP_INFO_GLOBAL_LOG, 0 };
+
+/* if no log file specified, log entry goes to stderr */
+int _logfd = 2;
+
+/* close old log file and open a new one */
+static nscd_rc_t
+_nscd_set_lf(
+ char *lf)
+{
+ int newlogfd;
+ char *me = "_nscd_set_lf";
+
+ /*
+ * don't try and open the log file /dev/null
+ */
+ if (lf == NULL || *lf == 0) {
+ /* ignore empty log file specs */
+ return (NSCD_SUCCESS);
+ } else if (strcmp(lf, "/dev/null") == 0) {
+ (void) strlcpy(logfile, lf, PATH_MAX);
+ if (_logfd >= 0)
+ (void) close(_logfd);
+ _logfd = -1;
+ return (NSCD_SUCCESS);
+ } else if (strcmp(lf, "stderr") == 0) {
+ (void) strlcpy(logfile, lf, PATH_MAX);
+ if (_logfd != -1 && _logfd != 2)
+ (void) close(_logfd);
+ _logfd = 2;
+ return (NSCD_SUCCESS);
+ } else {
+
+ /*
+ * In order to open this file securely, we'll try a few tricks
+ */
+
+ if ((newlogfd = open(lf, O_EXCL|O_WRONLY|O_CREAT, 0644)) < 0) {
+ /*
+ * File already exists... now we need to get cute
+ * since opening a file in a world-writeable directory
+ * safely is hard = it could be a hard link or a
+ * symbolic link to a system file.
+ */
+ struct stat before;
+
+ if (lstat(lf, &before) < 0) {
+ _nscd_logit(me, "Cannot open new "
+ "logfile \"%s\": %sn", lf, strerror(errno));
+ return (NSCD_CFG_FILE_OPEN_ERROR);
+ }
+
+ if (S_ISREG(before.st_mode) && /* no symbolic links */
+ (before.st_nlink == 1) && /* no hard links */
+ (before.st_uid == 0)) { /* owned by root */
+ if ((newlogfd =
+ open(lf, O_APPEND|O_WRONLY, 0644)) < 0) {
+ _nscd_logit(me, "Cannot open new "\
+ "logfile \"%s\": %s\n", lf,
+ strerror(errno));
+ return (NSCD_CFG_FILE_OPEN_ERROR);
+ }
+ } else {
+ _nscd_logit(me, "Cannot use specified "
+ "logfile \"%s\": "\
+ "file is/has links or isn't owned by "\
+ "root\n", lf);
+ return (NSCD_CFG_FILE_OPEN_ERROR);
+ }
+ }
+
+ (void) close(_logfd);
+ (void) strlcpy(logfile, lf, PATH_MAX);
+ _logfd = newlogfd;
+ _nscd_logit(me, "Start of new logfile %s\n", lf);
+ }
+ return (NSCD_SUCCESS);
+}
+
+
+/* log an entry to the configured nscd log file */
+void
+_nscd_logit(
+ char *funcname,
+ char *format,
+ ...)
+{
+ static mutex_t loglock = DEFAULTMUTEX;
+ struct timeval tv;
+ char tid_buf[32];
+ char pid_buf[32];
+ char buffer[LOGBUFLEN];
+ int safechars, offset;
+ va_list ap;
+
+ if (_logfd < 0)
+ return;
+
+ va_start(ap, format);
+
+ if (gettimeofday(&tv, NULL) != 0 ||
+ ctime_r(&tv.tv_sec, buffer, LOGBUFLEN) == NULL) {
+ (void) snprintf(buffer, LOGBUFLEN,
+ "<time conversion failed>\t");
+ } else {
+ (void) sprintf(tid_buf, "--%d", thr_self());
+ (void) sprintf(pid_buf, "--%ld", getpid());
+ /*
+ * ctime_r() includes some stuff we don't want;
+ * adjust length to overwrite " YYYY\n" and
+ * include tid string length.
+ */
+ offset = strlen(buffer) - 6;
+ safechars = LOGBUFLEN - (offset - 1);
+ (void) snprintf(buffer + offset,
+ safechars, ".%.4ld%s%s\t%s:\n\t\t",
+ tv.tv_usec/100, tid_buf, pid_buf,
+ funcname);
+ }
+ offset = strlen(buffer);
+ safechars = LOGBUFLEN - (offset - 1);
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ if (vsnprintf(buffer + offset, safechars, format, ap) >
+ safechars) {
+ (void) strncat(buffer, "...\n", LOGBUFLEN);
+ }
+
+ (void) mutex_lock(&loglock);
+ (void) write(_logfd, buffer, strlen(buffer));
+ logstats.entries_logged++;
+ (void) mutex_unlock(&loglock);
+
+ va_end(ap);
+}
+
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_log_notify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void *cookie)
+{
+
+ nscd_cfg_global_log_t *logcfg;
+ int off;
+
+ /*
+ * At init time, the whole group of config params are received.
+ * At update time, group or individual parameter value could
+ * be received.
+ */
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+
+ logcfg = (nscd_cfg_global_log_t *)data;
+
+ _nscd_log_comp = logcfg->debug_comp;
+ _nscd_log_level = logcfg->debug_level;
+
+ /*
+ * logcfg->logfile should have been opened
+ * by _nscd_cfg_log_verify()
+ */
+
+ return (NSCD_SUCCESS);
+ }
+
+ /*
+ * individual config parameter
+ */
+ off = offsetof(nscd_cfg_global_log_t, debug_comp);
+ if (pdesc->p_offset == off) {
+ _nscd_log_comp = *(nscd_cfg_bitmap_t *)data;
+ return (NSCD_SUCCESS);
+ }
+
+ off = offsetof(nscd_cfg_global_log_t, debug_level);
+ if (pdesc->p_offset == off)
+ _nscd_log_level = *(nscd_cfg_bitmap_t *)data;
+
+ /*
+ * logcfg->logfile should have been opened
+ * by _nscd_cfg_log_verify()
+ */
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_log_verify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+ nscd_cfg_global_log_t *logcfg;
+ nscd_cfg_bitmap_t bt;
+ int off;
+
+ /*
+ * There is no switch db specific config params
+ * for the nscd log component. It is a bug if
+ * the input param description is global.
+ */
+ if (_nscd_cfg_flag_is_not_set(pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL))
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+
+ /*
+ * At init time, the whole group of config params are received.
+ * At update time, group or individual parameter value could
+ * be received.
+ */
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+
+ logcfg = (nscd_cfg_global_log_t *)data;
+
+ if (_nscd_cfg_bitmap_valid(logcfg->debug_comp,
+ NSCD_LOG_ALL) == 0)
+ return (NSCD_CFG_SYNTAX_ERROR);
+
+ if (_nscd_cfg_bitmap_valid(logcfg->debug_level,
+ NSCD_LOG_LEVEL_ALL) == 0)
+ return (NSCD_CFG_SYNTAX_ERROR);
+
+ if (logcfg->logfile != NULL)
+ return (_nscd_set_lf(logcfg->logfile));
+
+ return (NSCD_SUCCESS);
+ }
+
+ /*
+ * individual config parameter
+ */
+
+ off = offsetof(nscd_cfg_global_log_t, debug_comp);
+ if (pdesc->p_offset == off) {
+
+ bt = *(nscd_cfg_bitmap_t *)data;
+ if (_nscd_cfg_bitmap_valid(bt, NSCD_LOG_ALL) == 0)
+ return (NSCD_CFG_SYNTAX_ERROR);
+
+ return (NSCD_SUCCESS);
+ }
+
+ off = offsetof(nscd_cfg_global_log_t, debug_level);
+ if (pdesc->p_offset == off) {
+
+ bt = *(nscd_cfg_bitmap_t *)data;
+ if (_nscd_cfg_bitmap_valid(bt, NSCD_LOG_LEVEL_ALL) == 0)
+ return (NSCD_CFG_SYNTAX_ERROR);
+
+ return (NSCD_SUCCESS);
+ }
+
+ off = offsetof(nscd_cfg_global_log_t, logfile);
+ if (pdesc->p_offset == off) {
+ if (data != NULL)
+ return (_nscd_set_lf((char *)data));
+ else
+ return (NSCD_SUCCESS);
+ }
+
+ return (NSCD_CFG_PARAM_DESC_ERROR);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_log_get_stat(
+ void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)(void *stat),
+ nscd_cfg_error_t **errorp)
+{
+
+ *(nscd_cfg_stat_global_log_t **)stat = &logstats;
+
+ /* indicate the statistics are static, i.e., do not free */
+ *dflag = _nscd_cfg_flag_set(*dflag, NSCD_CFG_DFLAG_STATIC_DATA);
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * set the name of the current log file and make it current.
+ */
+nscd_rc_t
+_nscd_set_log_file(
+ char *name)
+{
+ nscd_rc_t rc;
+ nscd_cfg_handle_t *h;
+
+ rc = _nscd_cfg_get_handle("logfile", NULL, &h, NULL);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ rc = _nscd_cfg_set(h, name, NULL);
+ _nscd_cfg_free_handle(h);
+ if (rc != NSCD_SUCCESS)
+ exit(rc);
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * Map old nscd debug level to new one and make it current.
+ * -- debug component: NSCD_LOG_CACHE
+ * -- debug level:
+ * -- DBG_OFF --> NSCD_LOG_LEVEL_NONE
+ * -- DBG_CANT_FIND --> NSCD_LOG_LEVEL_ERROR
+ * -- DBG_DBG_NETLOOKUPS --> NSCD_LOG_LEVEL_ERROR
+ * -- DBG_ALL --> NSCD_LOG_LEVEL_ALL
+ */
+nscd_rc_t
+_nscd_set_debug_level(
+ int level)
+{
+ nscd_rc_t rc;
+ nscd_cfg_handle_t *h;
+ int l;
+ int c;
+
+ rc = _nscd_cfg_get_handle("debug-components", NULL, &h, NULL);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ c = NSCD_LOG_CACHE;
+
+ if (level < 0)
+ c = -1 * level / 10000;
+ rc = _nscd_cfg_set(h, &c, NULL);
+ _nscd_cfg_free_handle(h);
+ if (rc != NSCD_SUCCESS)
+ exit(rc);
+
+ rc = _nscd_cfg_get_handle("debug-level", NULL, &h, NULL);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ if (level == DBG_OFF)
+ l = NSCD_LOG_LEVEL_NONE;
+ else if (level >= DBG_CANT_FIND)
+ l = NSCD_LOG_LEVEL_ERROR;
+ else if (level >= DBG_NETLOOKUPS)
+ l = NSCD_LOG_LEVEL_ERROR;
+ else if (level >= DBG_ALL)
+ l = NSCD_LOG_LEVEL_ALL;
+
+ if (level < 0)
+ l = -1 * level % 10000;
+
+ rc = _nscd_cfg_set(h, &l, NULL);
+ _nscd_cfg_free_handle(h);
+ if (rc != NSCD_SUCCESS)
+ exit(rc);
+
+ return (NSCD_SUCCESS);
+}
diff --git a/usr/src/cmd/nscd/nscd_log.h b/usr/src/cmd/nscd/nscd_log.h
new file mode 100644
index 0000000000..784c74cf01
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_log.h
@@ -0,0 +1,96 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_LOG_H
+#define _NSCD_LOG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "nscd_common.h"
+
+/*
+ * nscd logging options
+ */
+/*
+ * components: select more than one by OR'ing
+ */
+#define NSCD_LOG_NONE 0x0000
+#define NSCD_LOG_ACCESS_INFO 0x0001
+#define NSCD_LOG_INT_ADDR 0x0002
+#define NSCD_LOG_NSW_STATE 0x0004
+#define NSCD_LOG_GETENT_CTX 0x0008
+#define NSCD_LOG_SWITCH_ENGINE 0x0010
+#define NSCD_LOG_CONFIG 0x0020
+#define NSCD_LOG_FRONT_END 0x0040
+#define NSCD_LOG_CACHE 0x0080
+#define NSCD_LOG_SMF_MONITOR 0x0100
+#define NSCD_LOG_ADMIN 0x0200
+#define NSCD_LOG_SELF_CRED 0x0400
+#define NSCD_LOG_ALL 0x07ff
+
+/*
+ * debug level: select more than one by OR'ing
+ */
+#define NSCD_LOG_LEVEL_NONE 0x0000
+#define NSCD_LOG_LEVEL_CANT_FOUND 0x0001
+#define NSCD_LOG_LEVEL_ALERT 0x0002
+#define NSCD_LOG_LEVEL_CRIT 0x0004
+#define NSCD_LOG_LEVEL_ERROR 0x0008
+#define NSCD_LOG_LEVEL_WARNING 0x0010
+#define NSCD_LOG_LEVEL_NOTICE 0x0020
+#define NSCD_LOG_LEVEL_INFO 0x0040
+#define NSCD_LOG_LEVEL_DEBUG 0x0080
+#define NSCD_LOG_LEVEL_ALL 0x00ff
+
+/*
+ * _nscd_log_comp and _nscd_log_level defined in nscd_log.c
+ */
+extern int _nscd_log_comp;
+extern int _nscd_log_level;
+
+#define _NSCD_LOG(comp, lvl) if ((_nscd_log_comp & (comp)) && \
+ (_nscd_log_level & (lvl))) \
+ _nscd_logit
+
+#define _NSCD_LOG_IF(comp, lvl) if ((_nscd_log_comp & (comp)) && \
+ (_nscd_log_level & (lvl)))
+
+
+/*
+ * prototypes
+ */
+void _nscd_logit(char *funcname, char *format, ...);
+nscd_rc_t _nscd_set_debug_level(int level);
+nscd_rc_t _nscd_set_log_file(char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_LOG_H */
diff --git a/usr/src/cmd/nscd/nscd_nswcfgst.c b/usr/src/cmd/nscd/nscd_nswcfgst.c
new file mode 100644
index 0000000000..7659b9706d
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_nswcfgst.c
@@ -0,0 +1,262 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+#include "nscd_config.h"
+#include "nscd_log.h"
+#include "nscd_switch.h"
+
+/*
+ * Configuration data for the nscd switch functions.
+ */
+nscd_cfg_global_switch_t nscd_switch_cfg_g;
+nscd_cfg_switch_t *nscd_switch_cfg;
+
+/*
+ * statistics of the nscd switch functions.
+ */
+nscd_cfg_stat_global_switch_t nscd_switch_stats_g;
+nscd_cfg_stat_switch_t *nscd_switch_stats;
+
+/*
+ * cookie is set up by the verify function for passing to
+ * the notify function
+ */
+typedef struct {
+ struct __nsw_switchconfig_v1 *cfg;
+ char *cfgstr;
+} nsw_cfg_cookie_t;
+
+nscd_rc_t
+_nscd_alloc_switch_cfg()
+{
+ nscd_switch_cfg = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_switch_t));
+ if (nscd_switch_cfg == NULL)
+ return (NSCD_NO_MEMORY);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_alloc_switch_stats()
+{
+
+ nscd_switch_stats = calloc(NSCD_NUM_DB,
+ sizeof (nscd_cfg_stat_switch_t));
+ if (nscd_switch_stats == NULL)
+ return (NSCD_NO_MEMORY);
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_switch_notify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void *cookie)
+{
+
+ void *dp;
+ nscd_rc_t rc;
+ nsw_cfg_cookie_t *ck = (nsw_cfg_cookie_t *)cookie;
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
+ _nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+ /*
+ * group data is received, copy in the
+ * entire strcture
+ */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL)) {
+ nscd_switch_cfg_g = *(nscd_cfg_global_switch_t *)data;
+ } else {
+ nscd_switch_cfg[nswdb->index] =
+ *(nscd_cfg_switch_t *)data;
+
+ }
+ } else {
+ /*
+ * individual paramater is received: copy in the
+ * parameter value except for nsw-config-string.
+ */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag,
+ NSCD_CFG_PFLAG_GLOBAL)) {
+ dp = (char *)&nscd_switch_cfg_g + pdesc->p_offset;
+ (void) memcpy(dp, data, pdesc->p_size);
+ } else {
+ dp = (char *)&nscd_switch_cfg[nswdb->index] +
+ pdesc->p_offset;
+ if (pdesc->p_offset !=
+ offsetof(nscd_cfg_switch_t, nsw_config_string))
+ (void) memcpy(dp, data, pdesc->p_size);
+ }
+ }
+
+ /*
+ * cookie contains data for the switch policy config
+ */
+ if (cookie != NULL) {
+ rc = _nscd_create_sw_struct(nswdb->index, nswdb->name,
+ ck->cfgstr, ck->cfg, NULL);
+ if (rc != NSCD_SUCCESS) {
+ (void) __nsw_freeconfig_v1(ck->cfg);
+ free(ck);
+ return (rc);
+ }
+ free(ck);
+ }
+
+ if (_nscd_cfg_flag_is_not_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA))
+ free(data);
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_switch_verify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+ char *me = "_nscd_cfg_switch_verify";
+ nscd_cfg_switch_t *cfg;
+ char *nswcfgstr;
+ int size;
+ struct __nsw_switchconfig_v1 *switchcfg = NULL;
+ enum __nsw_parse_err err;
+ nsw_cfg_cookie_t *ck;
+ char buf[MAX_NSSWITCH_CONFIG_STRING_SZ];
+ char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
+
+ /*
+ * global config data has nothing special to verify
+ */
+ if (_nscd_cfg_flag_is_set(pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL))
+ return (NSCD_SUCCESS);
+
+ *cookie = NULL;
+
+ /*
+ * switch policy string is the one to parse and verify
+ */
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
+ _nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+
+ /* get it from the group data */
+ cfg = (nscd_cfg_switch_t *)data;
+ nswcfgstr = cfg->nsw_config_string;
+ } else {
+ /* not group, and not the switch policy string, return */
+ if (pdesc->p_offset != offsetof(nscd_cfg_switch_t,
+ nsw_config_string))
+ return (NSCD_SUCCESS);
+
+ /* the data itself is the string */
+ nswcfgstr = (char *)data;
+ }
+
+ /*
+ * convert the string into struct __nsw_switchconfig_v1
+ */
+ size = MAX_NSSWITCH_CONFIG_STRING_SZ;
+ if (strlcpy(buf, nswcfgstr, size) >= size) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("switch policy string too long (\"%s : %s\" > %d)"),
+ nswdb->name, nswcfgstr, size);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ if (*errorp)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_SYNTAX_ERROR, msg);
+
+ return (NSCD_CFG_SYNTAX_ERROR);
+ }
+ switchcfg = _nsw_getoneconfig_v1(nswdb->name, buf, &err);
+ if (switchcfg == NULL) {
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("syntax error: switch policy string (%s : %s) rc = %d"),
+ nswdb->name, nswcfgstr, err);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "%s\n", msg);
+
+ if (*errorp)
+ *errorp = _nscd_cfg_make_error(
+ NSCD_CFG_SYNTAX_ERROR, msg);
+
+ return (NSCD_CFG_SYNTAX_ERROR);
+ }
+
+ /* save the __nsw_switchconfig_v1 for the notify function */
+ ck = calloc(1, sizeof (nsw_cfg_cookie_t));
+ if (ck == NULL) {
+ (void) __nsw_freeconfig_v1(switchcfg);
+ return (NSCD_CFG_SYNTAX_ERROR);
+ }
+ ck->cfg = switchcfg;
+ ck->cfgstr = nswcfgstr;
+ *cookie = ck;
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_switch_get_stat(
+ void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)(void *stat),
+ nscd_cfg_error_t **errorp)
+{
+
+ if (_nscd_cfg_flag_is_set(sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL)) {
+ *stat = &NSCD_SW_STATS_G;
+ } else
+ *stat = &NSCD_SW_STATS(nswdb->index);
+
+ /* indicate the statistics are static, i.e., do not free */
+ *dflag = _nscd_cfg_flag_set(*dflag, NSCD_CFG_DFLAG_STATIC_DATA);
+
+ return (NSCD_SUCCESS);
+}
diff --git a/usr/src/cmd/nscd/nscd_nswconfig.c b/usr/src/cmd/nscd/nscd_nswconfig.c
new file mode 100644
index 0000000000..f6e669324d
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_nswconfig.c
@@ -0,0 +1,686 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <libscf_priv.h>
+#include <string.h>
+#include <assert.h>
+#include "nscd_switch.h"
+#include "nscd_log.h"
+#include "nscd_db.h"
+
+/*
+ * nscd database for each source. It contains backend
+ * info (nscd_be_info_t) for each naming database.
+ * Protected by nscd_src_backend_db_lock.
+ */
+nscd_db_t ***nscd_src_backend_db;
+static rwlock_t nscd_src_backend_db_lock = DEFAULTRWLOCK;
+
+/*
+ * nsswitch config monitored by nscd. Protected by
+ * readers/writer lock nscd_nsw_config_lock
+ */
+nscd_nsw_config_t ***nscd_nsw_config;
+static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK;
+
+/*
+ * nsswitch source index/name array
+ * (allow 16 user-defined nsswitch sources/backends)
+ */
+#define NSCD_NUM_SRC_UDEF 16
+nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
+int _nscd_cfg_num_nsw_src_all;
+
+static void
+free_nscd_nsw_config(
+ nscd_acc_data_t *data)
+{
+
+ nscd_nsw_config_t *nsw_cfg = *(nscd_nsw_config_t **)data;
+ char *me = "free_nscd_nsw_config";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing nscd nsw config %p \n", nsw_cfg);
+ if (nsw_cfg == NULL)
+ return;
+
+ if (nsw_cfg->db_name != NULL)
+ free(nsw_cfg->db_name);
+ if (nsw_cfg->nsw_cfg_str != NULL)
+ free(nsw_cfg->nsw_cfg_str);
+ if (nsw_cfg->nsw_config != NULL)
+ (void) __nsw_freeconfig_v1(nsw_cfg->nsw_config);
+ if (nsw_cfg->src_idx != NULL)
+ free(nsw_cfg->src_idx);
+
+ free(nsw_cfg);
+}
+
+
+void
+_nscd_free_nsw_config(
+ nscd_nsw_config_t *nswcfg)
+{
+ free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg);
+}
+
+void
+_nscd_free_all_nsw_config()
+{
+
+ nscd_nsw_config_t **nsw_cfg;
+ int i;
+ char *me = "_nscd_free_all_nsw_config";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing all nscd nsw config \n");
+
+ (void) rw_wrlock(&nscd_nsw_config_lock);
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ if ((nsw_cfg = nscd_nsw_config[i]) == NULL)
+ continue;
+
+ nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set(
+ (nscd_acc_data_t *)nsw_cfg, NULL);
+ }
+ (void) rw_unlock(&nscd_nsw_config_lock);
+}
+
+
+static void
+free_nsw_backend_info_db(nscd_acc_data_t *data)
+{
+
+ nscd_db_t *db = *(nscd_db_t **)data;
+ char *me = "free_nsw_backend_info_db";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing nsw backend info db %p\n", db);
+
+ if (db == NULL)
+ return;
+
+ _nscd_free_db(db);
+
+}
+
+void
+_nscd_free_all_nsw_backend_info_db()
+{
+
+ nscd_db_t **db;
+ int i;
+ char *me = " _nscd_free_all_nsw_backend_info_db";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing all nsw backend info db\n");
+
+ (void) rw_wrlock(&nscd_src_backend_db_lock);
+ for (i = 0; i < NSCD_NUM_SRC; i++) {
+
+ if ((db = nscd_src_backend_db[i]) == NULL)
+ continue;
+
+ nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set(
+ (nscd_acc_data_t *)db, NULL);
+ }
+ (void) rw_unlock(&nscd_src_backend_db_lock);
+}
+
+/*
+ * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)'
+ * source. Create one entry for each source/database pair
+ * (e.g., ldap:passwd, nis:hosts, etc).
+ */
+static nscd_rc_t
+_nscd_populate_nsw_backend_info_db(int srci)
+{
+ nscd_be_info_t be_info, *bi;
+ nss_backend_finder_t *bf;
+ nscd_nsw_config_t *nsw_cfg;
+ int i, size;
+ nscd_db_entry_t *db_entry;
+ char *src = NSCD_NSW_SRC_NAME(srci);
+ const char *dbn;
+ char *me = "_nscd_populate_nsw_backend_info_db";
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ if (nscd_nsw_config[i] == NULL)
+ continue;
+
+ nsw_cfg = *nscd_nsw_config[i];
+ dbn = NSCD_NSW_DB_NAME(i);
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "adding backend info for <%s : %s>\n", src, dbn);
+
+ (void) memset(&be_info, 0, sizeof (be_info));
+
+ for (bf = nsw_cfg->fe_params.finders; bf != 0;
+ bf = bf->next) {
+ nss_backend_constr_t c;
+
+ c = (*bf->lookup)(bf->lookup_priv, dbn, src,
+ &be_info.finder_priv);
+
+ if (c != 0) {
+ be_info.be_constr = c;
+ be_info.finder = bf;
+ break;
+ }
+ }
+ if (be_info.be_constr == NULL) {
+ /*
+ * Couldn't find the backend anywhere.
+ * This is fine, some backend just don't
+ * support certain databases.
+ */
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to find backend info "
+ "for <%s : %s>\n", src, dbn);
+ }
+
+ size = sizeof (nscd_be_info_t);
+
+ db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO,
+ dbn, size, 1, 1);
+
+ if (db_entry == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate db entry for "
+ "<%s : %s>\n", src, dbn);
+ return (NSCD_NO_MEMORY);
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "adding be db entry %p for <%s : %s> to db %p: "
+ "constr = %p\n", db_entry, src, dbn,
+ *nscd_src_backend_db[srci], be_info.be_constr);
+
+ bi = (nscd_be_info_t *)*(db_entry->data_array);
+ *bi = be_info;
+
+ (void) _nscd_rdlock((nscd_acc_data_t *)
+ nscd_src_backend_db[srci]);
+ (void) _nscd_add_db_entry(*nscd_src_backend_db[srci],
+ dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST);
+ (void) _nscd_rw_unlock((nscd_acc_data_t *)
+ nscd_src_backend_db[srci]);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/*
+ * create data structures (used by the switch engine) based
+ * on the input switch policy configuration and database
+ * name and indexes
+ */
+nscd_rc_t
+_nscd_create_sw_struct(
+ int dbi,
+ const char *dbn,
+ const char *cfgstr,
+ void *swcfgv1,
+ nscd_nsw_params_t *params)
+{
+ char *me = "_nscd_create_sw_struct";
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nscd_nsw_config_t *nsw_cfg = NULL;
+ nscd_nsw_config_t **nsw_cfg_p = NULL;
+ struct __nsw_switchconfig_v1 *swcfg = NULL;
+ struct __nsw_lookup_v1 *lkp;
+ enum __nsw_parse_err err;
+ int maxsrc;
+ int *src_idx_a = NULL;
+ int j, k;
+
+ /*
+ * if the nsw config string has been parsed into
+ * a struct __nsw_switchconfig_v1, use it. If not,
+ * create the struct.
+ */
+ if (swcfgv1 != NULL)
+ swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1;
+ else {
+ char *cstr;
+
+ cstr = strdup(cfgstr);
+ if (cstr == NULL)
+ return (NSCD_NO_MEMORY);
+
+ /*
+ * parse the nsw config string and create
+ * a struct __nsw_switchconfig_v1
+ */
+ swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err);
+ free(cstr);
+ if (swcfg == NULL) {
+ rc = NSCD_CFG_SYNTAX_ERROR;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: unable to process nsw config string\n");
+ goto error_exit;
+ }
+ }
+
+ /* allocate the space for a nscd_nsw_config_t */
+ nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
+ if (nsw_cfg == NULL) {
+ rc = NSCD_NO_MEMORY;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: unable to allocate an nscd_nsw_config_t\n");
+ goto error_exit;
+ }
+
+ /* need to know how many backends (sources) */
+ maxsrc = swcfg->num_lookups;
+ nsw_cfg->max_src = maxsrc;
+
+ /*
+ * allocate an array to store the index for each
+ * backend (source)
+ */
+ src_idx_a = calloc(1, maxsrc * sizeof (int));
+ if (src_idx_a == NULL) {
+ rc = NSCD_NO_MEMORY;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: unable to allocate an array for source index\n");
+ goto error_exit;
+ }
+
+ /*
+ * set the index for each backend (source)
+ */
+ lkp = swcfg->lookups;
+ for (j = 0; j < maxsrc; j++) {
+ char *usrc;
+
+ for (k = 0; k < NSCD_NUM_SRC &&
+ NSCD_NSW_SRC_NAME(k) != NULL &&
+ strcmp(lkp->service_name,
+ NSCD_NSW_SRC_NAME(k)) != 0; k++);
+
+ if (k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "unknown nsw source name %s\n",
+ lkp->service_name);
+ usrc = strdup(lkp->service_name);
+ if (usrc == NULL) {
+ rc = NSCD_NO_MEMORY;
+ _NSCD_LOG(NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to strdup() source name\n");
+ goto error_exit;
+ }
+ NSCD_NSW_SRC_NAME(k) = usrc;
+
+ rc = _nscd_populate_nsw_backend_info_db(k);
+ if (rc != NSCD_SUCCESS) {
+ free(usrc);
+ NSCD_NSW_SRC_NAME(k) = NULL;
+ goto error_exit;
+ }
+ } else if (NSCD_NSW_SRC_NAME(k) == NULL) {
+ /*
+ * number of user-defined source exceeded
+ */
+ rc = NSCD_CFG_SYNTAX_ERROR;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: number of user_defined source exceeded\n");
+
+ goto error_exit;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "setting source index array [%d] = %d (%s)\n",
+ j, k, lkp->service_name);
+
+ src_idx_a[j] = k;
+
+ lkp = lkp->next;
+ if (lkp == NULL) break;
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "number of nsw sources = %d\n", nsw_cfg->max_src);
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "next nsw source is %s\n", lkp->service_name);
+ }
+
+ /* set it up to reference count the switch policy config */
+ nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
+ NSCD_DATA_NSW_CONFIG,
+ sizeof (nscd_nsw_config_t **),
+ free_nscd_nsw_config,
+ NSCD_ALLOC_RWLOCK);
+
+ if (nsw_cfg_p == NULL) {
+ rc = NSCD_NO_MEMORY;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate a new nsw config DB\n");
+ goto error_exit;
+ }
+ *nsw_cfg_p = nsw_cfg;
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new nsw config DB %p allocated\n", nsw_cfg_p);
+
+ /* save all the data in the new nscd_nsw_config_t */
+ nsw_cfg->db_name = strdup(dbn);
+ nsw_cfg->nsw_cfg_str = strdup(cfgstr);
+ if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) {
+ rc = NSCD_NO_MEMORY;
+ goto error_exit;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "switch policy \"%s\" for database is \"%s\"\n",
+ nsw_cfg->db_name, nsw_cfg->nsw_cfg_str);
+
+ nsw_cfg->nsw_config = swcfg;
+ nsw_cfg->src_idx = src_idx_a;
+
+ /*
+ * set default frontend params and if necessary call initf()
+ * to initialize or override
+ */
+ nsw_cfg->fe_params.max_active_per_src = 10;
+ nsw_cfg->fe_params.max_dormant_per_src = 1;
+ nsw_cfg->fe_params.finders = nss_default_finders;
+ if (params != NULL) {
+ nsw_cfg->fe_params = params->p;
+
+ if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
+ params->nswcfg = nsw_cfg_p;
+ /*
+ * this nsw_cfg is not meant to last long, no need
+ * to set up the nsw state and getent bases, just
+ * exit with NSCD_SUCCESS
+ */
+ nsw_cfg->nobase = 1;
+ goto error_exit;
+ }
+ } else
+ (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
+
+ /*
+ * activate the new nscd_nsw_config_t, the old one
+ * will either be deleted or left on the side (and be
+ * deleted eventually)
+ */
+ nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
+ (nscd_acc_data_t *)nscd_nsw_config[dbi],
+ (nscd_acc_data_t *)nsw_cfg_p);
+
+ /*
+ * also create a new nsw state base
+ */
+ if ((rc = _nscd_init_nsw_state_base(dbi, 1)) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to initialize a nsw state base(%d)\n", dbi);
+ goto error_exit;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new nsw state base(%d) %p created\n", dbi,
+ nscd_nsw_state_base[dbi]);
+
+ /*
+ * also create a new getent context base
+ */
+ if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to initialize a getent context base(%d)\n", dbi);
+ goto error_exit;
+ }
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new getent context base(%d) %p created\n", dbi,
+ nscd_getent_ctx_base[dbi]);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new nsw config created (database = %s, "
+ "config = %s)\n", dbn, cfgstr);
+
+
+ error_exit:
+
+ if (rc != NSCD_SUCCESS) {
+
+ if (swcfgv1 == NULL && swcfg != NULL)
+ (void) __nsw_freeconfig_v1(swcfg);
+ if (src_idx_a != NULL)
+ free(src_idx_a);
+ if (nsw_cfg_p)
+ free(nsw_cfg_p);
+ if (nsw_cfg != NULL) {
+ if (nsw_cfg->db_name != NULL)
+ free(nsw_cfg->db_name);
+ if (nsw_cfg->nsw_cfg_str != NULL)
+ free(nsw_cfg->nsw_cfg_str);
+ free(nsw_cfg);
+ }
+
+ return (rc);
+ } else
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+create_nsw_config(int dbi)
+{
+
+ nscd_nsw_config_t *nsw_cfg = NULL;
+ nscd_nsw_config_t **nsw_cfg_p = NULL;
+ char *me = "create_nsw_config";
+
+ /*
+ * if pseudo-databases (initf function not defined),
+ * don't bother now
+ */
+ if (nscd_nss_db_initf[dbi] == NULL)
+ return (NSCD_SUCCESS);
+
+ /* allocate the space for a nscd_nsw_config_t */
+ nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
+ if (nsw_cfg == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate a nsw config structure\n");
+ return (NSCD_NO_MEMORY);
+ }
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw config structure %pallocated\n", nsw_cfg);
+
+ nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
+ NSCD_DATA_NSW_CONFIG,
+ sizeof (nscd_nsw_config_t **),
+ free_nscd_nsw_config,
+ NSCD_ALLOC_RWLOCK);
+
+ if (nsw_cfg_p == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate a pointer to nsw config structure\n");
+ return (NSCD_NO_MEMORY);
+ }
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw config pointer = %p\n", nsw_cfg_p);
+
+ nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi));
+ if (nsw_cfg->db_name == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to strdup the db name\n");
+ return (NSCD_NO_MEMORY);
+ }
+
+ /*
+ * set default frontend params and then call initf()
+ * to initialize or override
+ */
+ nsw_cfg->fe_params.max_active_per_src = 10;
+ nsw_cfg->fe_params.max_dormant_per_src = 1;
+ nsw_cfg->fe_params.finders = nss_default_finders;
+ (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
+
+ /*
+ * activate the new nscd_nsw_config_t
+ */
+ *nsw_cfg_p = nsw_cfg;
+ nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
+ (nscd_acc_data_t *)nscd_nsw_config[dbi],
+ (nscd_acc_data_t *)nsw_cfg_p);
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw config %p activated\n", nsw_cfg);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_init_all_nsw_config(void)
+{
+ nscd_rc_t rc;
+ int i;
+ char *me = "_nscd_init_all_nsw_config";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing all nsw config\n");
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+ if ((rc = create_nsw_config(i)) != NSCD_SUCCESS)
+ return (rc);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static nscd_rc_t
+init_nsw_be_info_db(int srci)
+{
+ nscd_db_t *ret, **db_p;
+ char *me = "init_nsw_be_info_db";
+
+ ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL);
+
+ if (ret == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate a nsw be info database\n");
+ return (NSCD_NO_MEMORY);
+ }
+
+ /* set up to reference count the backend info db */
+ db_p = (nscd_db_t **)
+ _nscd_alloc(NSCD_DATA_BACKEND_INFO_DB,
+ sizeof (nscd_db_t **),
+ free_nsw_backend_info_db,
+ NSCD_ALLOC_RWLOCK);
+
+ if (db_p == NULL) {
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to allocate the pointer to the nsw "
+ "be info database\n");
+ return (NSCD_NO_MEMORY);
+ }
+
+ *db_p = ret;
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p);
+
+ nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set(
+ (nscd_acc_data_t *)nscd_src_backend_db[srci],
+ (nscd_acc_data_t *)db_p);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_init_all_nsw_be_info_db(void)
+{
+
+ int i;
+ nscd_rc_t rc;
+ char *me = "_nscd_init_all_nsw_be_info_db";
+
+ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing all nsw be info databases\n");
+
+ for (i = 0; i < NSCD_NUM_SRC; i++) {
+ if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS)
+ return (rc);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+
+nscd_rc_t
+_nscd_alloc_nsw_config()
+{
+ nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **));
+ if (nscd_nsw_config == NULL)
+ return (NSCD_NO_MEMORY);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_alloc_nsw_be_info_db()
+{
+ int i;
+
+ _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + NSCD_NUM_SRC_UDEF;
+ nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **));
+ if (nscd_src_backend_db == NULL)
+ return (NSCD_NO_MEMORY);
+
+ /* also allocate/init the nsswitch source index/name array */
+ _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc(
+ _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t));
+ for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++)
+ (_nscd_cfg_nsw_src_all + i)->index = -1;
+
+ (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src,
+ _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t));
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_populate_nsw_backend_info()
+{
+ int i;
+ nscd_rc_t rc;
+
+ for (i = 0; i < NSCD_NUM_SRC; i++) {
+ if (NSCD_NSW_SRC_NAME(i) == NULL)
+ continue;
+ rc = _nscd_populate_nsw_backend_info_db(i);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+ }
+
+ return (NSCD_SUCCESS);
+}
diff --git a/usr/src/cmd/nscd/nscd_nswparse.c b/usr/src/cmd/nscd/nscd_nswparse.c
new file mode 100644
index 0000000000..ac90788e91
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_nswparse.c
@@ -0,0 +1,379 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+#define __NSS_PRIVATE_INTERFACE
+#include "nsswitch_priv.h"
+#undef __NSS_PRIVATE_INTERFACE
+
+#define islabel(c) (isalnum(c) || (c) == '_')
+
+/*
+ * The _nsw_getoneconfig_v1() in this file parses the switch policy
+ * configuration for a switch database, e.g.,
+ *
+ * hosts: nis [NOTFOUND=return] files
+ * or
+ * printers: user files nis
+ */
+
+/*
+ * Local routines
+ */
+static char *skip(char **, char);
+static char *labelskip(char *);
+static char *spaceskip(char *);
+static void freeconf_v1(struct __nsw_switchconfig_v1 *);
+static int alldigits(char *);
+
+/*
+ *
+ * With the "lookup control" feature, the default criteria for NIS, NIS+,
+ * and any new services (e.g. ldap) will be:
+ * [SUCCESS=return NOTFOUND=continue UNAVAIL=continue TRYAGAIN=forever]
+ *
+ * For backward compat, NIS via NIS server in DNS forwarding mode will be:
+ * [SUCCESS=return NOTFOUND=continue UNAVAIL=continue TRYAGAIN=continue]
+ *
+ * And also for backward compat, the default criteria for DNS will be:
+ * [SUCCESS=return NOTFOUND=continue UNAVAIL=continue TRYAGAIN=continue]
+ */
+
+
+
+/*
+ * The BIND resolver normally will retry several times on server non-response.
+ * But now with the "lookup control" feature, we don't want the resolver doing
+ * many retries, rather we want it to return control (reasonably) quickly back
+ * to the switch engine. However, when TRYAGAIN=N or TRYAGAIN=forever is
+ * not explicitly set by the admin in the conf file, we want the old "resolver
+ * retry a few times" rather than no retries at all.
+ */
+static int dns_tryagain_retry = 3;
+
+/*
+ * For backward compat (pre "lookup control"), the dns default behavior is
+ * soft lookup.
+ */
+static void
+set_dns_default_lkp(struct __nsw_lookup_v1 *lkp)
+{
+ if (strcasecmp(lkp->service_name, "dns") == 0) {
+ lkp->actions[__NSW_TRYAGAIN] =
+ __NSW_TRYAGAIN_NTIMES;
+ lkp->max_retries = dns_tryagain_retry;
+ }
+}
+
+static void
+freeconf_v1(struct __nsw_switchconfig_v1 *cfp)
+{
+ if (cfp) {
+ if (cfp->dbase)
+ free(cfp->dbase);
+ if (cfp->lookups) {
+ struct __nsw_lookup_v1 *nex, *cur;
+ for (cur = cfp->lookups; cur; cur = nex) {
+ free(cur->service_name);
+ nex = cur->next;
+ free(cur);
+ }
+ }
+ free(cfp);
+ }
+}
+
+/* give the next non-alpha character */
+static char *
+labelskip(char *cur)
+{
+ char *p = cur;
+ while (islabel(*p))
+ ++p;
+ return (p);
+}
+
+/* give the next non-space character */
+static char *
+spaceskip(char *cur)
+{
+ char *p = cur;
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ return (p);
+}
+
+/*
+ * terminate the *cur pointed string by null only if it is
+ * followed by "key" surrounded by zero or more spaces and
+ * return value is the same as the original *cur pointer and
+ * *cur pointer is advanced to the first non {space, key} char
+ * followed by the key. Otherwise, return NULL and keep
+ * *cur unchanged.
+ */
+static char *
+skip(char **cur, char key)
+{
+ char *p, *tmp;
+ char *q = *cur;
+ int found, tmpfound;
+
+ tmp = labelskip(*cur);
+ p = tmp;
+ found = (*p == key);
+ if (found) {
+ *p++ = '\0'; /* overwrite the key */
+ p = spaceskip(p);
+ } else {
+ while (*p == ' ' || *p == '\t') {
+ tmpfound = (*++p == key);
+ if (tmpfound) {
+ found = tmpfound;
+ /* null terminate the return token */
+ *tmp = '\0';
+ p++; /* skip the key */
+ }
+ }
+ }
+ if (!found)
+ return (NULL); /* *cur unchanged */
+ *cur = p;
+ return (q);
+}
+
+/* Return 1 if the string contains all digits, else return 0. */
+static int
+alldigits(char *s)
+{
+ for (; *s; s++)
+ if (!isdigit(*s))
+ return (0);
+ return (1);
+}
+
+struct __nsw_switchconfig_v1 *
+_nsw_getoneconfig_v1(const char *name, char *linep, enum __nsw_parse_err *errp)
+ /* linep Nota Bene: not const char * */
+ /* errp Meanings are abused a bit */
+{
+ struct __nsw_switchconfig_v1 *cfp;
+ struct __nsw_lookup_v1 *lkp, **lkq;
+ int end_crit;
+ action_t act;
+ char *p, *tokenp;
+
+ *errp = __NSW_CONF_PARSE_SUCCESS;
+
+ if ((cfp = calloc(1, sizeof (struct __nsw_switchconfig_v1)))
+ == NULL) {
+ *errp = __NSW_CONF_PARSE_SYSERR;
+ return (NULL);
+ }
+ cfp->dbase = strdup(name);
+ lkq = &cfp->lookups;
+
+ /* linep points to a naming service name */
+ for (;;) {
+ int i;
+
+ /* white space following the last service */
+ if (*linep == '\0' || *linep == '\n') {
+ return (cfp);
+ }
+ if ((lkp = calloc(1, sizeof (struct __nsw_lookup_v1)))
+ == NULL) {
+ *errp = __NSW_CONF_PARSE_SYSERR;
+ freeconf_v1(cfp);
+ return (NULL);
+ }
+
+ *lkq = lkp;
+ lkq = &lkp->next;
+
+ for (i = 0; i < __NSW_STD_ERRS_V1; i++)
+ if (i == __NSW_SUCCESS)
+ lkp->actions[i] = __NSW_RETURN;
+ else if (i == __NSW_TRYAGAIN)
+ lkp->actions[i] = __NSW_TRYAGAIN_FOREVER;
+ else
+ lkp->actions[i] = __NSW_CONTINUE;
+
+ /* get criteria for the naming service */
+ if (tokenp = skip(&linep, '[')) { /* got criteria */
+
+ /* premature end, illegal char following [ */
+ if (!islabel(*linep))
+ goto barf_line;
+ lkp->service_name = strdup(tokenp);
+ cfp->num_lookups++;
+
+ set_dns_default_lkp(lkp);
+
+ end_crit = 0;
+
+ /* linep points to a switch_err */
+ for (;;) {
+ int ntimes = 0; /* try again max N times */
+ int dns_continue = 0;
+
+ if ((tokenp = skip(&linep, '=')) == NULL) {
+ goto barf_line;
+ }
+
+ /* premature end, ill char following = */
+ if (!islabel(*linep))
+ goto barf_line;
+
+ /* linep points to the string following '=' */
+ p = labelskip(linep);
+ if (*p == ']')
+ end_crit = 1;
+ else if (*p != ' ' && *p != '\t')
+ goto barf_line;
+ *p++ = '\0'; /* null terminate linep */
+ p = spaceskip(p);
+ if (!end_crit) {
+ if (*p == ']') {
+ end_crit = 1;
+ *p++ = '\0';
+ } else if (*p == '\0' || *p == '\n') {
+ return (cfp);
+ } else if (!islabel(*p))
+ /* p better be the next switch_err */
+ goto barf_line;
+ }
+ if (strcasecmp(linep, __NSW_STR_RETURN) == 0)
+ act = __NSW_RETURN;
+ else if (strcasecmp(linep,
+ __NSW_STR_CONTINUE) == 0) {
+ if (strcasecmp(lkp->service_name,
+ "dns") == 0 &&
+ strcasecmp(tokenp,
+ __NSW_STR_TRYAGAIN)
+ == 0) {
+ /*
+ * Add one more condition
+ * so it retries only if it's
+ * "dns [TRYAGAIN=continue]"
+ */
+ dns_continue = 1;
+ act = __NSW_TRYAGAIN_NTIMES;
+ } else
+ act = __NSW_CONTINUE;
+ } else if (strcasecmp(linep,
+ __NSW_STR_FOREVER) == 0)
+ act = __NSW_TRYAGAIN_FOREVER;
+ else if (alldigits(linep)) {
+ act = __NSW_TRYAGAIN_NTIMES;
+ ntimes = atoi(linep);
+ if (ntimes < 0 || ntimes > INT_MAX)
+ ntimes = 0;
+ }
+ else
+ goto barf_line;
+
+ if (__NSW_SUCCESS_ACTION(act) &&
+ strcasecmp(tokenp,
+ __NSW_STR_SUCCESS) == 0) {
+ lkp->actions[__NSW_SUCCESS] = act;
+ } else if (__NSW_NOTFOUND_ACTION(act) &&
+ strcasecmp(tokenp,
+ __NSW_STR_NOTFOUND) == 0) {
+ lkp->actions[__NSW_NOTFOUND] = act;
+ } else if (__NSW_UNAVAIL_ACTION(act) &&
+ strcasecmp(tokenp,
+ __NSW_STR_UNAVAIL) == 0) {
+ lkp->actions[__NSW_UNAVAIL] = act;
+ } else if (__NSW_TRYAGAIN_ACTION(act) &&
+ strcasecmp(tokenp,
+ __NSW_STR_TRYAGAIN) == 0) {
+ lkp->actions[__NSW_TRYAGAIN] = act;
+ if (strcasecmp(lkp->service_name,
+ "nis") == 0)
+ lkp->actions[
+ __NSW_NISSERVDNS_TRYAGAIN]
+ = act;
+ if (act == __NSW_TRYAGAIN_NTIMES)
+ lkp->max_retries =
+ dns_continue ?
+ dns_tryagain_retry : ntimes;
+ } else {
+ /*EMPTY*/
+ /*
+ * convert string tokenp to integer
+ * and put in long_errs
+ */
+ }
+ if (end_crit) {
+ linep = spaceskip(p);
+ if (*linep == '\0' || *linep == '\n')
+ return (cfp);
+ break; /* process next naming service */
+ }
+ linep = p;
+ } /* end of while loop for a name service's criteria */
+ } else {
+ /*
+ * no criteria for this naming service.
+ * linep points to name service, but not null
+ * terminated.
+ */
+ p = labelskip(linep);
+ if (*p == '\0' || *p == '\n') {
+ *p = '\0';
+ lkp->service_name = strdup(linep);
+ set_dns_default_lkp(lkp);
+ cfp->num_lookups++;
+ return (cfp);
+ }
+ if (*p != ' ' && *p != '\t')
+ goto barf_line;
+ *p++ = '\0';
+ lkp->service_name = strdup(linep);
+ set_dns_default_lkp(lkp);
+ cfp->num_lookups++;
+ linep = spaceskip(p);
+ }
+ } /* end of while(1) loop for a name service */
+
+barf_line:
+ freeconf_v1(cfp);
+ *errp = __NSW_CONF_PARSE_NOPOLICY;
+ return (NULL);
+}
+
+int
+__nsw_freeconfig_v1(
+ struct __nsw_switchconfig_v1 *conf)
+{
+ freeconf_v1(conf);
+ return (0);
+}
diff --git a/usr/src/cmd/nscd/nscd_nswstate.c b/usr/src/cmd/nscd/nscd_nswstate.c
new file mode 100644
index 0000000000..2f571e4e3f
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_nswstate.c
@@ -0,0 +1,786 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "nscd_switch.h"
+#include "nscd_log.h"
+
+/*
+ * nscd_nsw_state_t list for each nss database. Protected
+ * by the readers/writer lock nscd_nsw_state_base_lock.
+ */
+nscd_nsw_state_base_t **nscd_nsw_state_base;
+static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK;
+
+static void
+_nscd_free_nsw_state(
+ nscd_nsw_state_t *s)
+{
+
+ int i;
+ char *me = "_nscd_free_nsw_state";
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing nsw state = %p\n", s);
+
+ if (s == NULL)
+ return;
+
+ if (s->nsw_cfg_p != NULL)
+ /*
+ * an nsw state without base does not reference
+ * count the nsw config data (ie not using a
+ * shared one), so the one created for it should
+ * be freed
+ */
+ if ((*s->nsw_cfg_p)->nobase != 1)
+ _nscd_release((nscd_acc_data_t *)s->nsw_cfg_p);
+ else
+ _nscd_free_nsw_config(*s->nsw_cfg_p);
+
+ if (s->be_db_pp != NULL) {
+ for (i = 0; i < s->max_src; i++) {
+ if (s->be_db_pp[i] == NULL)
+ continue;
+ _nscd_release((nscd_acc_data_t *)s->be_db_pp[i]);
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "release db be ptr %p\n", s->be_db_pp[i]);
+ }
+ free(s->be_db_pp);
+ }
+
+ if (s->be != NULL) {
+ for (i = 0; i < s->max_src; i++) {
+ if (s->be[i] == NULL)
+ continue;
+ if (s->getent == 1)
+ (void) NSS_INVOKE_DBOP(s->be[i],
+ NSS_DBOP_ENDENT, 0);
+ (void) NSS_INVOKE_DBOP(s->be[i],
+ NSS_DBOP_DESTRUCTOR, 0);
+ }
+ free(s->be);
+ }
+
+ s->base = NULL;
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state %p freed \n", s);
+
+ free(s);
+}
+
+static void
+_nscd_free_nsw_state_base(
+ nscd_acc_data_t *data)
+{
+ nscd_nsw_state_base_t *base = (nscd_nsw_state_base_t *)data;
+ nscd_nsw_state_t *s, *ts;
+ int i;
+ char *me = "_nscd_free_nsw_state_base";
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing db state base %p\n", base);
+
+ if (base == NULL)
+ return;
+
+ for (i = 0; i < 2; i++) {
+ if (i == 1)
+ s = base->nsw_state.first;
+ else
+ s = base->nsw_state_thr.first;
+
+ while (s != NULL) {
+ ts = s->next;
+ _nscd_free_nsw_state(s);
+ s = ts;
+ }
+ }
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state base %p freed \n", base);
+}
+
+void
+_nscd_free_all_nsw_state_base()
+{
+ nscd_nsw_state_base_t *base;
+ int i;
+ char *me = "_nscd_free_all_nsw_state_base";
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing all db state base\n");
+
+ (void) rw_wrlock(&nscd_nsw_state_base_lock);
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ base = nscd_nsw_state_base[i];
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "freeing db state base (%d) %p \n", i, base);
+
+ if (base == NULL)
+ continue;
+
+ nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
+ _nscd_set((nscd_acc_data_t *)base, NULL);
+ }
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+}
+
+static nscd_nsw_state_t *
+_nscd_create_nsw_state(
+ nscd_nsw_params_t *params)
+{
+ nscd_nsw_state_t *s;
+ nscd_nsw_config_t *nsw_cfg;
+ nscd_db_t **be_db_p, *be_db;
+ int i, nobe = 1;
+ char *me = "_nscd_create_nsw_state";
+
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "creating nsw state...\n");
+
+ s = calloc(1, sizeof (nscd_nsw_state_t));
+ if (s == NULL) {
+ if ((*s->nsw_cfg_p)->nobase != 1)
+ _nscd_release((nscd_acc_data_t *)params->nswcfg);
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to allocate a nsw state\n");
+ return (NULL);
+ } else
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state %p allocated\n", s);
+
+ s->dbi = params->dbi;
+ s->next = NULL;
+
+ nsw_cfg = *params->nswcfg;
+
+ s->nsw_cfg_p = params->nswcfg;
+ s->config = nsw_cfg->nsw_config;
+ s->max_src = nsw_cfg->max_src;
+ s->p = params->p;
+
+ s->be = calloc(s->max_src, sizeof (nss_backend_t **));
+ if (s->be == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to allocate s->be\n");
+
+ _nscd_free_nsw_state(s);
+ return (NULL);
+ } else {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "db be array %p allocated\n", s->be);
+ }
+
+ s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***));
+ if (s->be_db_pp == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to allocate s->be_db_pp\n");
+ _nscd_free_nsw_state(s);
+ return (NULL);
+ } else {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "be_db_pp array %p allocated\n", s->be_db_pp);
+ }
+
+ /* create the source:database backends */
+ for (i = 0; i < s->max_src; i++) {
+ nss_backend_t *be;
+ int srci;
+ char *srcn;
+ const char *dbn;
+ struct __nsw_lookup_v1 *lkp;
+ const nscd_db_entry_t *dbe;
+ nscd_be_info_t *be_info;
+
+ if (i == 0)
+ lkp = s->config->lookups;
+ else
+ lkp = lkp->next;
+ if (lkp == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: lkp is NULL\n");
+ _nscd_free_nsw_state(s);
+ return (NULL);
+ }
+
+ srci = nsw_cfg->src_idx[i];
+ srcn = lkp->service_name;
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "source name = %s, index = %d\n", srcn, srci);
+
+ be_db_p = (nscd_db_t **)_nscd_get(
+ (nscd_acc_data_t *)nscd_src_backend_db[srci]);
+ if (be_db_p == NULL) {
+ _nscd_free_nsw_state(s);
+ return (NULL);
+ }
+ be_db = *be_db_p;
+ s->be_db_pp[i] = be_db_p;
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "be db ptr array %p referenced\n", be_db_p);
+
+ be_info = NULL;
+ be = NULL;
+ dbn = params->p.name;
+ dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO,
+ (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
+ if (dbe != NULL)
+ be_info = (nscd_be_info_t *)*(dbe->data_array);
+
+ if (be_info == NULL || be_info->be_constr == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no backend info or be_constr is NULL "
+ "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci),
+ dbn);
+ } else
+ be = (be_info->be_constr)(dbn,
+ NSCD_NSW_SRC_NAME(srci), 0);
+
+ if (be == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to init be for <%s : %s>\n",
+ NSCD_NSW_SRC_NAME(srci), dbn);
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "releasing db be ptr %p\n", be_db_p);
+
+ _nscd_release((nscd_acc_data_t *)be_db_p);
+ s->be_db_pp[i] = NULL;
+
+ continue;
+ }
+
+ s->be[i] = be;
+ nobe = 0;
+ }
+
+ if (nobe == 1) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "NO backend found, returning NULL\n");
+
+ _nscd_free_nsw_state(s);
+ return (NULL);
+ }
+
+ return (s);
+}
+
+static nscd_rc_t
+_get_nsw_state_int(
+ nss_db_root_t *rootp,
+ nscd_nsw_params_t *params,
+ thread_t *tid)
+{
+
+ nscd_nsw_state_t *ret = NULL;
+ nscd_nsw_config_t **nswcfg;
+ nscd_nsw_state_base_t *base;
+ nscd_state_ctrl_t *ctrl_p;
+ int thread_only = 0, wait_cond = 0;
+ char *me = "_get_nsw_state_int";
+ int dbi;
+ nscd_rc_t rc;
+
+ dbi = params->dbi;
+
+ /*
+ * no nsw state will be reused, if asked to use
+ * default config. So create the new structures
+ * used by the switch engine and the new nsw state
+ */
+ if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
+ rc = _nscd_create_sw_struct(dbi, (char *)params->p.name,
+ (char *)params->p.default_config, NULL, params);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no base nsw config created for %s (sources: %s)\n",
+ params->p.name, params->p.default_config);
+
+ ret = _nscd_create_nsw_state(params);
+ if (ret == NULL)
+ return (NSCD_CREATE_NSW_STATE_FAILED);
+ rootp->s = (struct nss_db_state *)ret;
+ return (NSCD_SUCCESS);
+ }
+
+ /*
+ * if getting a nsw state for a request from the compat
+ * backend, create the new switch structures if this
+ * is the first time around for a passwd, shadow, group,
+ * audit_user, or user_attr database
+ */
+ if (params->compati != -1) {
+
+ nscd_nsw_config_t **nswcfg1;
+ int i = params->compati;
+
+ nswcfg = (nscd_nsw_config_t **)_nscd_get(
+ (nscd_acc_data_t *)nscd_nsw_config[i]);
+
+ /*
+ * if nsw data structures not created yet, get the
+ * config string from the passwd_compat or
+ * group_compat DB and create the structures
+ */
+ if (nswcfg == NULL) {
+ nswcfg1 = (nscd_nsw_config_t **)_nscd_get(
+ (nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]);
+ if (nswcfg1 == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "no nsw config for %s\n",
+ params->p.name);
+ return (NSCD_CREATE_NSW_STATE_FAILED);
+ }
+
+ rc = _nscd_create_sw_struct(i, params->p.name,
+ (*nswcfg1)->nsw_cfg_str, NULL, params);
+ _nscd_release((nscd_acc_data_t *)nswcfg1);
+ if (rc != NSCD_SUCCESS)
+ return (rc);
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw config created for %s (%s)\n",
+ params->p.name, (*nswcfg1)->nsw_cfg_str);
+ } else
+ _nscd_release((nscd_acc_data_t *)nswcfg);
+ }
+
+ (void) rw_rdlock(&nscd_nsw_state_base_lock);
+ base = nscd_nsw_state_base[dbi];
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+ if (base == NULL)
+ assert(base != NULL);
+
+ /*
+ * If list is not empty, return the first one on list.
+ * Otherwise, create and return a new db state if the
+ * limit is not reached. if reacehed, wait for the 'one
+ * is available' signal.
+ */
+ assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock(
+ (nscd_acc_data_t *)base));
+
+ if (tid == NULL) {
+ ctrl_p = &base->nsw_state;
+ } else {
+ thread_only = 1;
+ ctrl_p = &base->nsw_state_thr;
+
+ _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
+ _nscd_logit(me, "per thread nsw state info: \n");
+ _nscd_logit(me, "tid = %d\n", *tid);
+ _nscd_logit(me, "tid in base = %d\n", base->tid);
+ _nscd_logit(me, "number of free nsw_state = %d\n",
+ ctrl_p->free);
+ _nscd_logit(me, "number of nsw state allocated = %d\n",
+ ctrl_p->allocated);
+ _nscd_logit(me, "first nsw state on list = %p\n",
+ ctrl_p->first);
+ _nscd_logit(me, "number of waiter = %d\n",
+ ctrl_p->waiter);
+ }
+ }
+
+ if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max)
+ wait_cond = 1;
+ else if (thread_only && base->used_by_thr && base->tid != *tid)
+ wait_cond = 1;
+
+ if (wait_cond) {
+
+ ctrl_p->waiter++;
+
+ while (wait_cond) {
+ if (!thread_only)
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "waiting for nsw state signal\n");
+ else
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "waiting for per thread "
+ "nsw state signal\n");
+
+ if (thread_only) {
+ _nscd_cond_wait((nscd_acc_data_t *)base,
+ &base->thr_cond);
+
+ if (base->used_by_thr == 0 &&
+ ctrl_p->first != NULL)
+ wait_cond = 0;
+ } else {
+ _nscd_cond_wait((nscd_acc_data_t *)base, NULL);
+
+ if (ctrl_p->first != NULL)
+ wait_cond = 0;
+ }
+
+ if (!thread_only)
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "woke from cond wait ...wait_cond = %d\n",
+ wait_cond);
+ else
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "woke from cond wait (per thread) "
+ "...wait_cond = %d\n", wait_cond);
+
+ }
+
+ ctrl_p->waiter--;
+ }
+
+ if (ctrl_p->first == NULL) {
+ int geti;
+
+ /*
+ * for lookup calls from the compat backend
+ * uses the switch policy for passwd_compat
+ * or group_compat
+ */
+ if (params->compati != -1)
+ geti = params->compati;
+ else
+ geti = params->dbi;
+
+ params->nswcfg = (nscd_nsw_config_t **)_nscd_get(
+ (nscd_acc_data_t *)nscd_nsw_config[geti]);
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got a nsw config %p for index %d\n",
+ params->nswcfg, geti);
+
+ ctrl_p->first = _nscd_create_nsw_state(params);
+ if (ctrl_p->first != NULL) {
+ ctrl_p->first->base = base;
+
+ if (tid == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "got a new nsw_state %p\n", ctrl_p->first);
+ } else {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "got a new per thread nsw_state %p\n",
+ ctrl_p->first);
+ }
+ ctrl_p->allocated++;
+ ctrl_p->free++;
+ } else {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
+ (me, "error: unable to obtain a nsw state\n");
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+ return (NSCD_CREATE_NSW_STATE_FAILED);
+ }
+ }
+
+ ret = ctrl_p->first;
+ ctrl_p->first = ret->next;
+ ret->next = NULL;
+ ctrl_p->free--;
+ if (thread_only) {
+ base->tid = *tid;
+ base->used_by_thr = 1;
+
+ _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
+ _nscd_logit(me, "\t\t\tgot a per thread nsw "
+ "state %p: \n", ret);
+ _nscd_logit(me, "tid = %d\n", *tid);
+ _nscd_logit(me, "tid in base = %d\n", base->tid);
+ _nscd_logit(me, "number of free nsw_state = %d\n",
+ ctrl_p->free);
+ _nscd_logit(me, "number od nsw state allocated = %d\n",
+ ctrl_p->allocated);
+ _nscd_logit(me, "first nsw state on list = %p\n",
+ ctrl_p->first);
+ _nscd_logit(me, "number of waiter = %d\n",
+ ctrl_p->waiter);
+ }
+ }
+ else
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got old nsw state %p\n", ret);
+
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+
+ rootp->s = (struct nss_db_state *)ret;
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_get_nsw_state(
+ nss_db_root_t *rootp,
+ nscd_nsw_params_t *params)
+{
+ return (_get_nsw_state_int(rootp, params, NULL));
+}
+
+nscd_rc_t
+_nscd_get_nsw_state_thread(
+ nss_db_root_t *rootp,
+ nscd_nsw_params_t *params)
+{
+ thread_t tid = thr_self();
+ return (_get_nsw_state_int(rootp, params, &tid));
+}
+
+
+static void
+_put_nsw_state_int(
+ nscd_nsw_state_t *s,
+ thread_t *tid)
+{
+
+ nscd_nsw_state_base_t *base;
+ nscd_state_ctrl_t *ctrl_p;
+ int thread_only = 0;
+ char *me = "_put_nsw_state_int";
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "put back a nsw state\n");
+
+ if (s == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state is NULL, nothing to put back\n");
+ return;
+ }
+
+ /*
+ * no need to put back if the nsw state is not on any base
+ * but need to free the resources used
+ */
+ if ((*s->nsw_cfg_p)->nobase == 1) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no base nsw state, freeing resources ...\n");
+
+ _nscd_free_nsw_state(s);
+ return;
+ }
+
+ if (tid != NULL)
+ thread_only = 1;
+
+ base = s->base;
+
+ if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) {
+ /* base has been freed, free this db state */
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state base has been freed, freeing %p\n", s);
+ _nscd_free_nsw_state(s);
+ return;
+ }
+
+ if (thread_only)
+ ctrl_p = &base->nsw_state_thr;
+ else
+ ctrl_p = &base->nsw_state;
+
+ _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
+ _nscd_logit(me, "before returning the nsw state: \n");
+ _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
+ _nscd_logit(me, "tid in base = %d\n", base->tid);
+ _nscd_logit(me, "number of free nsw_state = %d\n",
+ ctrl_p->free);
+ _nscd_logit(me, "number od nsw state allocated = %d\n",
+ ctrl_p->allocated);
+ _nscd_logit(me, "first nsw state on list = %p\n",
+ ctrl_p->first);
+ _nscd_logit(me, "number of waiter = %d\n",
+ ctrl_p->waiter);
+ }
+
+ if (ctrl_p->first != NULL) {
+ s->next = ctrl_p->first;
+ ctrl_p->first = s;
+ } else {
+ ctrl_p->first = s;
+ s->next = NULL;
+ }
+ ctrl_p->free++;
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "signaling waiter thread_only = %d..\n", thread_only);
+
+ if (thread_only && ctrl_p->free == ctrl_p->allocated) {
+ assert(ctrl_p->first != NULL);
+ base->used_by_thr = 0;
+ if (ctrl_p->waiter > 0) {
+ (void) cond_signal(&base->thr_cond);
+ }
+ }
+
+ if (!thread_only && ctrl_p->waiter > 0) {
+
+ _nscd_cond_signal((nscd_acc_data_t *)base);
+ }
+
+ _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
+ _nscd_logit(me, "after the nsw state is returned: \n");
+ _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
+ _nscd_logit(me, "tid in base = %d\n", base->tid);
+ _nscd_logit(me, "number of free nsw_state = %d\n",
+ ctrl_p->free);
+ _nscd_logit(me, "number od nsw state allocated = %d\n",
+ ctrl_p->allocated);
+ _nscd_logit(me, "first nsw state on list = %p\n",
+ ctrl_p->first);
+ _nscd_logit(me, "tnumber of waiter = %d\n",
+ ctrl_p->waiter);
+ }
+
+ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "done putting back nsw state %p, thread_only = %d\n",
+ s, thread_only);
+
+ _nscd_mutex_unlock((nscd_acc_data_t *)base);
+
+}
+
+void
+_nscd_put_nsw_state(
+ nscd_nsw_state_t *s)
+{
+ _put_nsw_state_int(s, NULL);
+}
+
+void
+_nscd_put_nsw_state_thread(
+ nscd_nsw_state_t *s)
+{
+ thread_t tid = thr_self();
+ _put_nsw_state_int(s, &tid);
+}
+
+nscd_rc_t
+_nscd_init_nsw_state_base(
+ int dbi,
+ int lock)
+{
+ nscd_nsw_state_base_t *base = NULL;
+ char *me = "_nscd_init_nsw_state_base";
+
+ if (lock)
+ (void) rw_rdlock(&nscd_nsw_state_base_lock);
+
+ base = (nscd_nsw_state_base_t *)_nscd_alloc(
+ NSCD_DATA_NSW_STATE_BASE,
+ sizeof (nscd_nsw_state_base_t),
+ _nscd_free_nsw_state_base,
+ NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
+
+ if (base == NULL) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to allocate a nsw state base\n");
+ if (lock)
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+ return (NSCD_NO_MEMORY);
+ }
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw state base %p allocated\n", base);
+
+ /*
+ * initialize and activate the new nss_nsw_state base
+ */
+ base->dbi = dbi;
+ base->nsw_state.max = NSCD_SW_CFG(dbi).max_nsw_state_per_db;
+ base->nsw_state_thr.max = NSCD_SW_CFG(dbi).max_nsw_state_per_thread;
+
+ nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set(
+ (nscd_acc_data_t *)nscd_nsw_state_base[dbi],
+ (nscd_acc_data_t *)base);
+
+ if (lock)
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_init_all_nsw_state_base()
+{
+ int i;
+ nscd_rc_t rc;
+ char *me = "_nscd_init_all_nsw_state_base";
+
+ (void) rw_rdlock(&nscd_nsw_state_base_lock);
+
+ for (i = 0; i < NSCD_NUM_DB; i++) {
+
+ rc = _nscd_init_nsw_state_base(i, 0);
+
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to initialize a nsw db state "
+ "base (%d)\n", i);
+
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+ return (rc);
+ }
+ }
+ _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "all nsw state base initialized\n");
+
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+
+ return (NSCD_SUCCESS);
+}
+
+nscd_rc_t
+_nscd_alloc_nsw_state_base()
+{
+
+ (void) rw_rdlock(&nscd_nsw_state_base_lock);
+
+ nscd_nsw_state_base = calloc(NSCD_NUM_DB,
+ sizeof (nscd_nsw_state_base_t *));
+ if (nscd_nsw_state_base == NULL) {
+ (void) rw_unlock(&nscd_nsw_state_base_lock);
+ return (NSCD_NO_MEMORY);
+ }
+
+ (void) rw_rdlock(&nscd_nsw_state_base_lock);
+
+ return (NSCD_SUCCESS);
+}
diff --git a/usr/src/cmd/nscd/nscd_parse.c b/usr/src/cmd/nscd/nscd_parse.c
deleted file mode 100644
index 7555bb10b1..0000000000
--- a/usr/src/cmd/nscd/nscd_parse.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 1994-2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * routine to parse configuration file
- *
- * returns -1 on error, 0 on sucess. Error messages to log.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <synch.h>
-#include <sys/door.h>
-#include <unistd.h>
-
-#include "getxby_door.h"
-#include "server_door.h"
-#include "nscd.h"
-
-static int strbreak(char **, char *, char *);
-static int nscd_yesno(char *);
-static int nscd_set_integer(int *, char *, char *, int, int, int);
-static int nscd_set_short(short *, char *, char *, int, int, int);
-static int nscd_setyesno(int *, char *, char *, int);
-static int nscd_setyesno_sh(short *, char *, char *, int);
-static int nscd_set_cf(nsc_stat_t *, char *, int);
-
-int
-nscd_parse(char *progname, char *filename)
-{
- FILE *in;
- char buffer[255];
- char *fields [128];
- int errflg;
- int linecnt;
- int fieldcnt;
-
- if ((in = fopen(filename, "r")) == NULL) {
- logit("%s: open of configuration file %s failed: %s\n",
- progname, filename, strerror(errno));
- return (-1);
- }
-
- errflg = 0;
- linecnt = 0;
- while (fgets(buffer, sizeof (buffer), in) != NULL && !errflg) {
- nsc_stat_t *cache;
-
- linecnt++;
- if ((fieldcnt = strbreak(fields, buffer, " \t\n")) == 0) {
- /* blank */
- continue;
- }
-
- switch (*fields[0]) {
- case '#': /* comment ignore it */
- break;
- case 'p':
-
- if ((strcmp("positive-time-to-live", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_ttl_positive(cache, fields[1],
- atoi(fields[2])) < 0)
- errflg++;
-
- break;
-
- case 'n':
-
- if ((strcmp("negative-time-to-live", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_ttl_negative(cache, fields[1],
- atoi(fields[2])) < 0)
- errflg++;
-
- break;
-
- case 's':
-
- if ((strcmp("suggested-size", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_ss(cache, fields[1], atoi(fields[2])) < 0)
- errflg++;
-
- break;
-
- case 'k':
-
- if ((strcmp("keep-hot-count", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_khc(cache, fields[1], atoi(fields[2])) < 0)
- errflg++;
-
- break;
-
- case 'o':
-
- if ((strcmp("old-data-ok", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_odo(cache, fields[1],
- nscd_yesno(fields[2])) < 0) {
- errflg++;
- }
-
- break;
-
- case 'e':
- if ((strcmp("enable-cache", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_ec(cache, fields[1],
- nscd_yesno(fields[2])) < 0)
- errflg++;
- break;
-
- case 'c':
-
- if ((strcmp("check-files", fields[0]) != 0) ||
- (fieldcnt != 3) ||
- !(cache = getcacheptr(fields[1]))) {
- errflg++;
- break;
- }
-
- if (nscd_set_cf(cache, fields[1],
- nscd_yesno(fields[2])) < 0)
- errflg++;
- break;
-
-
- case 'l':
-
- if (strcmp("logfile", fields[0])) {
- errflg++;
- break;
- }
-
- if (nscd_set_lf(&current_admin, fields[1]) < 0)
- errflg++;
-
- break;
-
- case 'd':
- if (strcmp("debug-level", fields[0])) {
- errflg++;
- break;
- }
-
- if (nscd_set_dl(&current_admin, atoi(fields[1])) < 0)
- errflg++;
- break;
-
-
-
- default:
- errflg++;
- break;
- }
-
- if (errflg) {
- logit("Syntax error line %d of configuration file %s\n",
- linecnt, filename);
- return (-1);
- }
-
- }
-
- fclose(in);
- return (errflg?-1:0);
-}
-
-static int
-strbreak(char *field[], char *s, char *sep)
-{
- register int i;
- char *lasts;
-
- for (i = 0; field[i] = strtok_r((i?(char *)NULL:s), sep, &lasts); i++)
- ;
- return (i);
-}
-
-static int
-nscd_yesno(char *s)
-{
- if (strcmp(s, "yes") == 0)
- return (1);
-
- if (strcmp(s, "no") == 0)
- return (0);
- return (-1);
-}
-
-static int
-nscd_set_integer(int *addr, char *facility, char *cachename, int value,
- int min, int max)
-{
- if (value < min || value > max) {
- logit("attempted to set value of %s for %s to %d, which is not"
- "%d <= x <= %d\n", facility, cachename, value, min, max);
- return (-1);
- }
-
- if (*addr != value) {
- if (current_admin.debug_level)
- logit("Setting %s for %s to %d\n",
- facility, cachename, value);
- *addr = value;
- return (1);
- }
- return (0);
-}
-
-static int
-nscd_set_short(short *addr, char *facility, char *cachename, int value,
- int min, int max)
-{
- if (value < min || value > max) {
- logit("attempted to set value of %s for %s to %d, which is not "
- "%d <= x <= %d\n", facility, cachename, value, min, max);
- return (-1);
- }
-
- if (*addr != value) {
- if (current_admin.debug_level) {
- logit("Setting %s for %s to %d\n",
- facility, cachename, value);
- }
- *addr = value;
- return (1);
- }
- return (0);
-}
-
-static int
-nscd_setyesno(int *addr, char *facility, char *cachename, int value)
-{
- int yn;
-
- switch (yn = value) {
- case 1:
- case 0:
- if (*addr != yn) {
- if (current_admin.debug_level)
- logit("%s now %s for %s\n", facility,
- (yn?"enabled":"disabled"), cachename);
- *addr = yn;
- return (1);
- }
- else
- return (0);
- }
- return (-1);
-}
-
-static int
-nscd_setyesno_sh(short *addr, char *facility, char *cachename, int value)
-{
- int yn;
-
- switch (yn = value) {
- case 1:
- case 0:
- if (*addr != yn) {
- if (current_admin.debug_level) {
- logit("%s now %s for %s\n",
- facility, (yn?"enabled":"disabled"),
- cachename);
- }
- *addr = yn;
- return (1);
- }
- else
- return (0);
- }
- return (-1);
-}
-
-int
-nscd_set_dl(admin_t *ptr, int value)
-{
- return (nscd_set_integer(&(ptr->debug_level), "Debug level", "nscd",
- value, 0, 10));
-}
-
-int
-nscd_set_ec(nsc_stat_t *cache, char *name, int value)
-{
- return (nscd_setyesno(&(cache->nsc_enabled), "Caching", name, value));
-}
-
-static int
-nscd_set_cf(nsc_stat_t *cache, char *name, int value)
-{
- return (nscd_setyesno_sh(&(cache->nsc_check_files), "Checking files",
- name, value));
-}
-
-int
-nscd_set_khc(nsc_stat_t *cache, char *name, int value)
-{
- if (cache->nsc_pos_ttl < 600 && cache->nsc_keephot) {
- logit("ttl less than 600 seconds - disabling keep warm for %s "
- "cache\n", name);
- return (0);
- } else {
- return (nscd_set_short(&(cache->nsc_keephot),
- "Number of entries to keep hot", name, value, 0, 200));
- }
-}
-
-int
-nscd_set_odo(nsc_stat_t *cache, char *name, int value)
-{
- return (nscd_setyesno_sh(&(cache->nsc_old_data_ok),
- "Allowing return of old data", name, value));
-}
-
-int
-nscd_set_ss(nsc_stat_t *cache, char *name, int value)
-{
- return (nscd_set_integer(&(cache->nsc_suggestedsize),
- "Suggested size", name, value, 37, 1<<30));
-}
-
-int
-nscd_set_ttl_positive(nsc_stat_t *cache, char *name, int value)
-{
- int result = nscd_set_integer(&(cache->nsc_pos_ttl),
- "Time to live for positive cache entries",
- name, value, 0, 1<<30);
- if (cache->nsc_pos_ttl < 600 && cache->nsc_keephot) {
- cache->nsc_keephot = 0;
- logit("Disabling keephot for cache %s since ttl is less than "
- "600 seconds\n", name);
- }
- return (result);
-}
-
-int
-nscd_set_ttl_negative(nsc_stat_t *cache, char *name, int value)
-{
- int result = nscd_set_integer(&(cache->nsc_neg_ttl),
- "Time to live for negative cache entries",
- name, value, 0, 1 << 30);
- return (result);
-}
diff --git a/usr/src/cmd/nscd/nscd_selfcred.c b/usr/src/cmd/nscd/nscd_selfcred.c
new file mode 100644
index 0000000000..90b39bb88b
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_selfcred.c
@@ -0,0 +1,1589 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <synch.h>
+#include <thread.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <door.h>
+#include <libscf.h>
+#include <ucred.h>
+#include <sys/varargs.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/proc.h>
+#include <procfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/resource.h>
+#include <libscf.h>
+#include "nscd_door.h"
+#include "nscd_config.h"
+#include "nscd_log.h"
+#include "nscd_frontend.h"
+#include "nscd_selfcred.h"
+#include "nscd_admin.h"
+#include "nscd_common.h"
+#include "ns_sldap.h"
+
+extern int _logfd;
+static char *execpath;
+static char **execargv;
+static char *selfcred_dbs = NULL;
+
+static void *get_smf_prop(const char *var, char type, void *def_val);
+
+/* current self-cred configuration data being used */
+static nscd_cfg_global_selfcred_t nscd_selfcred_cfg_g;
+
+#define _NSCD_PUN_BLOCK 1024
+static uint8_t pu_nscd_enabled;
+static int max_pu_nscd = _NSCD_PUN_BLOCK;
+static int pu_nscd_ttl;
+
+static nscd_rc_t setup_ldap_backend();
+static nscd_rc_t init_user_proc_monitor();
+
+/*
+ * clild state
+ */
+typedef enum {
+ CHILD_STATE_NONE = 0,
+ CHILD_STATE_UIDKNOWN,
+ CHILD_STATE_FORKSENT,
+ CHILD_STATE_PIDKNOWN
+} child_state_t;
+
+
+typedef struct _child {
+ int child_slot;
+ int child_door;
+ pid_t child_pid;
+ uid_t child_uid;
+ gid_t child_gid;
+ child_state_t child_state;
+ int next_open;
+ mutex_t *mutex;
+ cond_t *cond;
+} child_t;
+
+static child_t **child = NULL;
+static mutex_t child_lock = DEFAULTMUTEX;
+static int open_head;
+static int open_tail;
+static int used_slot;
+
+/* nscd door id */
+extern int _doorfd;
+static pid_t main_uid = 0;
+
+/* nscd id: main, forker, or child */
+extern int _whoami;
+
+/* forker nscd pid */
+static pid_t forker_pid = 0;
+static pid_t forker_uid = 0;
+
+long activity = 0;
+mutex_t activity_lock = DEFAULTMUTEX;
+
+static int forking_door = -1;
+static mutex_t forking_lock = DEFAULTMUTEX;
+
+static void
+free_slot(int s)
+{
+ if (child[s] == NULL)
+ return;
+ free(child[s]->mutex);
+ free(child[s]->cond);
+ free(child[s]);
+ child[s] = NULL;
+}
+
+void
+_nscd_free_cslots()
+{
+
+ int i;
+
+ (void) mutex_lock(&child_lock);
+
+ for (i = 0; i < max_pu_nscd; i++)
+ free_slot(i);
+
+ open_head = -1;
+ open_tail = -1;
+ used_slot = -1;
+
+ (void) mutex_unlock(&child_lock);
+
+}
+
+static int
+init_slot(int s)
+{
+ child_t *ch;
+ char *me = "init_slot";
+
+ if (child[s] == NULL) {
+ child[s] = (child_t *)calloc(1, sizeof (child_t));
+ if (child[s] == NULL)
+ return (-1);
+ ch = child[s];
+
+ if ((ch->mutex = (mutex_t *)calloc(1,
+ sizeof (mutex_t))) == NULL) {
+ free(ch);
+ return (-1);
+ }
+ (void) mutex_init(ch->mutex, USYNC_THREAD, NULL);
+
+ if ((ch->cond = (cond_t *)calloc(1,
+ sizeof (cond_t))) == NULL) {
+ free(ch->mutex);
+ free(ch);
+ return (-1);
+ }
+ (void) cond_init(ch->cond, USYNC_THREAD, NULL);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "slot %d allocated\n", s);
+ } else
+ ch = child[s];
+
+ ch->child_slot = s;
+ ch->child_door = 0;
+ ch->child_state = CHILD_STATE_NONE;
+ ch->child_pid = 0;
+ ch->child_uid = 0;
+ ch->child_gid = 0;
+ ch->next_open = -1;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "slot %d initialized\n", s);
+
+ return (0);
+}
+
+static int
+_nscd_init_cslots()
+{
+ (void) mutex_lock(&child_lock);
+
+ child = (child_t **)calloc(max_pu_nscd, sizeof (child_t *));
+ if (child == NULL)
+ return (-1);
+
+ open_head = -1;
+ open_tail = -1;
+ used_slot = -1;
+
+ (void) mutex_unlock(&child_lock);
+
+ return (0);
+}
+
+static child_t *
+get_cslot(
+ uid_t uid,
+ int no_alloc)
+{
+ int i;
+ child_t *ch, *ret = NULL;
+ char *me = "get_cslot";
+
+ (void) mutex_lock(&child_lock);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "looking for uid %d (slot used = %d)\n", uid, used_slot);
+
+ /* first find the slot with a matching uid */
+ for (i = 0; i <= used_slot; i++) {
+ ch = child[i];
+ if (ch->child_state >= CHILD_STATE_UIDKNOWN &&
+ ch->child_uid == uid) {
+ ret = ch;
+ (void) mutex_unlock(&child_lock);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "slot %d found with uid %d\n",
+ ret->child_slot, ret->child_uid);
+
+ return (ret);
+ }
+ }
+
+ /* if no need to allocate a new slot, return NULL */
+ if (no_alloc == 1) {
+ (void) mutex_unlock(&child_lock);
+ return (ret);
+ }
+
+ /* no open slot ? get a new one */
+ if (open_head == -1) {
+ /* if no slot available, allocate more */
+ if (used_slot >= max_pu_nscd - 1) {
+ child_t **tmp;
+ int newmax = max_pu_nscd + _NSCD_PUN_BLOCK;
+
+ tmp = (child_t **)calloc(newmax, sizeof (child_t *));
+ if (tmp == NULL) {
+ (void) mutex_unlock(&child_lock);
+ return (ret);
+ }
+ (void) memcpy(tmp, child, sizeof (child_t) *
+ max_pu_nscd);
+ free(child);
+ child = tmp;
+ max_pu_nscd = newmax;
+ }
+ used_slot++;
+ if (init_slot(used_slot) == -1) {
+ used_slot--;
+ (void) mutex_unlock(&child_lock);
+ return (ret);
+ }
+ ch = child[used_slot];
+ } else {
+ ch = child[open_head];
+ open_head = ch->next_open;
+ /* got last one ? reset tail */
+ if (open_head == -1)
+ open_tail = -1;
+ ch->next_open = -1;
+ }
+
+ ch->child_uid = uid;
+ ch->child_state = CHILD_STATE_UIDKNOWN;
+ ret = ch;
+
+ (void) mutex_unlock(&child_lock);
+
+ return (ret);
+}
+
+static void
+return_cslot_nolock(child_t *ch)
+{
+
+ int slot = ch->child_slot;
+
+ /* have open slot ? add to and reset tail */
+ if (open_tail != -1) {
+ child[open_tail]->next_open = slot;
+ open_tail = slot;
+ } else {
+ /* no open slot ? make one */
+ open_head = open_tail = slot;
+ }
+
+ (void) init_slot(ch->child_slot);
+}
+
+static void
+return_cslot(child_t *ch)
+{
+
+ char *me = "return_cslot";
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "returning slot %d\n", ch->child_slot);
+
+ /* return if the slot has been returned by another thread */
+ if (ch->child_state == CHILD_STATE_NONE)
+ return;
+
+ (void) mutex_lock(&child_lock);
+
+ /* check one more time */
+ if (ch->child_state == CHILD_STATE_NONE) {
+ (void) mutex_unlock(&child_lock);
+ return;
+ }
+
+ return_cslot_nolock(ch);
+
+ (void) mutex_unlock(&child_lock);
+}
+
+static int
+selfcred_kill(
+ int fd)
+{
+ int ret;
+ char *me = "selfcred_kill";
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "sending kill to door %d\n", fd);
+
+ if (fd != -1)
+ ret = _nscd_doorcall_fd(fd, NSCD_KILL, NULL, 0,
+ NULL, 0, NULL);
+ else
+ ret = _nscd_doorcall(NSCD_KILL);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "kill request sent to door %d (rc = %d)\n", fd, ret);
+
+ return (ret);
+}
+
+
+void
+_nscd_kill_forker()
+{
+ (void) mutex_lock(&forking_lock);
+ if (forking_door != -1)
+ (void) selfcred_kill(forking_door);
+ forking_door = -1;
+ (void) mutex_unlock(&forking_lock);
+}
+
+void
+_nscd_kill_all_children()
+{
+ int i;
+ int ret;
+ char *me = "_nscd_kill_all_children";
+
+ (void) mutex_lock(&child_lock);
+ for (i = 0; i <= used_slot; i++) {
+ if (child[i] == NULL)
+ continue;
+
+ if (child[i]->child_state >= CHILD_STATE_PIDKNOWN) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "killing child process %d (doorfd %d)\n",
+ child[i]->child_pid, child[i]->child_door);
+
+ ret = selfcred_kill(child[i]->child_door);
+
+ if (ret != -1)
+ (void) kill(child[i]->child_pid, SIGTERM);
+ }
+ if (child[i]->child_state != CHILD_STATE_NONE)
+ (void) return_cslot_nolock(child[i]);
+ }
+ (void) mutex_unlock(&child_lock);
+}
+static int
+selfcred_pulse(
+ int fd)
+{
+ int ret;
+ char *me = "selfcred_pulse";
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "start monitoring door %d\n", fd);
+
+ ret = _nscd_doorcall_fd(fd, NSCD_PULSE |(_whoami & NSCD_WHOAMI),
+ NULL, 0, NULL, 0, NULL);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door (%d) monitor exited (rc = %d)\n", fd, ret);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+static void *
+forker_monitor(
+ void *arg)
+{
+ pid_t fpid;
+ char *fmri;
+ char *me = "forker_monitor";
+
+ /* wait until forker exits */
+ fpid = forker_pid;
+ (void) selfcred_pulse(forking_door);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+(me, "forker (pid = %d) exited or crashed, killing all child processes\n",
+ fpid);
+
+ (void) mutex_lock(&forking_lock);
+ forking_door = -1;
+ forker_pid = -1;
+ (void) mutex_unlock(&forking_lock);
+
+ /* forker exited/crashed, kill all the child processes */
+ _nscd_kill_all_children();
+
+ /* restart forker */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "restarting the forker ...\n");
+
+ switch (fpid = fork1()) {
+ case (pid_t)-1:
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "unable to fork and start the forker ...\n");
+
+ /* enter the maintenance mode */
+ if ((fmri = getenv("SMF_FMRI")) != NULL) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "entering maintenance mode ...\n");
+ smf_maintain_instance(fmri, SMF_TEMPORARY);
+ }
+ thr_exit((void *)1);
+ break;
+ case 0:
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "execv path = %s\n", execpath);
+
+ (void) execv(execpath, execargv);
+ exit(0);
+ break;
+ default:
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "new forker's pid is %d\n", fpid);
+ forker_pid = fpid;
+ break;
+ }
+
+ thr_exit((void *)0);
+
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
+}
+
+static void *
+child_monitor(
+ void *arg)
+{
+ child_t *ch = (child_t *)arg;
+ pid_t cpid;
+ char *me = "child_monitor";
+
+ /* wait until child exits */
+ cpid = ch->child_pid;
+ (void) selfcred_pulse(ch->child_door);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "child (pid = %d) exited or crashed ...\n", cpid);
+
+ /* return the slot used by the child */
+ return_cslot(ch);
+
+ thr_exit((void *)0);
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
+}
+
+
+void
+_nscd_proc_iamhere(
+ void *buf,
+ door_desc_t *dp,
+ uint_t n_desc,
+ int iam)
+{
+ int cslot;
+ child_t *ch;
+ int errnum;
+ ucred_t *uc = NULL;
+ uid_t uid;
+ nscd_imhere_t *ih;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_proc_iamhere";
+
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%d receives iamhere from %d\n", _whoami, iam);
+
+ if (door_ucred(&uc) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred failed: %s\n", strerror(errnum));
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
+ NSCD_DOOR_UCRED_ERROR);
+ }
+ uid = ucred_geteuid(uc);
+
+ switch (iam) {
+
+ case NSCD_MAIN:
+ if (_whoami == NSCD_MAIN || uid != main_uid) {
+ /*
+ * I'm main, or uid from door is not correct,
+ * this must be an imposter
+ */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "MAIN IMPOSTER CAUGHT!\n");
+
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_MAIN_IMPOSTER);
+ }
+ break;
+
+ case NSCD_FORKER:
+ if (_whoami == NSCD_FORKER || uid != forker_uid) {
+ /*
+ * I'm forker, or uid from door is not correct,
+ * this must be an imposter
+ */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "FORKER IMPOSTER CAUGHT!\n");
+
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_FORKER_IMPOSTER);
+ break;
+ }
+
+ /* only main needs to know the forker */
+ if (_whoami != NSCD_MAIN) {
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_WRONG_NSCD);
+ break;
+ }
+
+ if (ucred_getpid(uc) != forker_pid) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n",
+ ucred_getpid(uc), forker_pid);
+
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_FORKER_IMPOSTER);
+ break;
+ }
+
+ if (n_desc < 1) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "BAD FORKER, NO DOOR!\n");
+
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NO_DOOR);
+ break;
+ }
+
+ if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
+ dp->d_data.d_desc.d_descriptor > 0 &&
+ dp->d_data.d_desc.d_id != 0) {
+ (void) mutex_lock(&forking_lock);
+ if (forking_door != -1)
+ (void) close(forking_door);
+ forking_door = dp->d_data.d_desc.d_descriptor;
+ (void) mutex_unlock(&forking_lock);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "forking door is %d\n", forking_door);
+
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ } else {
+ NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
+ break;
+ }
+
+ /* monitor the forker nscd */
+ (void) thr_create(NULL, 0, forker_monitor, NULL,
+ THR_DETACHED, NULL);
+
+ break;
+
+ case NSCD_CHILD:
+ if (_whoami != NSCD_MAIN) {
+ /* child nscd can only talk to the main nscd */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "CHILD IMPOSTER CAUGHT!\n");
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_CHILD_IMPOSTER);
+ break;
+ }
+
+ /* get the main nscd assigned slot number */
+ ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf);
+ cslot = ih->slot;
+ (void) mutex_lock(&child_lock);
+ if (cslot < 0 || cslot >= max_pu_nscd)
+ ch = NULL;
+ else
+ ch = child[cslot];
+ (void) mutex_unlock(&child_lock);
+
+ if (ch == NULL) {
+ /* Bad slot number */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "bad slot number %d\n", cslot);
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
+ break;
+ }
+
+ if (uid != ch->child_uid) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n",
+ uid, ch->child_uid);
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_CHILD_IMPOSTER);
+ break;
+ }
+
+ if (ch->child_state != CHILD_STATE_UIDKNOWN &&
+ ch->child_state != CHILD_STATE_FORKSENT) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid slot/child state (%d) for uid %d\n",
+ ch->child_state, uid);
+
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_INVALID_SLOT_STATE);
+ break;
+ }
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "d_descriptor = %d, d_id = %lld\n",
+ dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id);
+
+ if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
+ dp->d_data.d_desc.d_descriptor > 0 &&
+ dp->d_data.d_desc.d_id != 0) {
+ (void) mutex_lock(ch->mutex);
+ if (ch->child_door != -1)
+ (void) close(ch->child_door);
+ ch->child_door = dp->d_data.d_desc.d_descriptor;
+ ch->child_pid = ucred_getpid(uc);
+ ch->child_state = CHILD_STATE_PIDKNOWN;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "child in slot %d has door %d\n",
+ cslot, ch->child_door);
+
+ /*
+ * let waiters know that the child is ready to
+ * serve
+ */
+ (void) cond_broadcast(ch->cond);
+ (void) mutex_unlock(ch->mutex);
+
+ /* monitor the child nscd */
+ (void) thr_create(NULL, 0, child_monitor,
+ ch, THR_DETACHED, NULL);
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ break;
+ } else {
+ NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
+ }
+ break;
+ }
+
+ ucred_free(uc);
+ uc = NULL;
+}
+
+void
+_nscd_proc_pulse(
+ void *buf,
+ int iam)
+{
+ long last_active;
+ int done = 0;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_proc_pulse";
+
+ /* only main nscd sends pulse */
+ if (iam != NSCD_MAIN) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_MAIN_IMPOSTER);
+ }
+
+ /* forker doesn't return stats, it just pauses */
+ if (_whoami == NSCD_FORKER) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "forker ready to pause ...\n");
+
+ /*CONSTCOND*/
+ while (1)
+ (void) pause();
+
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+ }
+
+ /* remember the current activity sequence number */
+ (void) mutex_lock(&activity_lock);
+ last_active = activity;
+ (void) mutex_unlock(&activity_lock);
+
+ while (!done) {
+
+ /* allow per_user_nscd_ttl seconds of inactivity */
+ (void) sleep(pu_nscd_ttl);
+
+ (void) mutex_lock(&activity_lock);
+ if (last_active == activity)
+ done = 1;
+ else {
+ last_active = activity;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "active, sleep again for %d seconds\n",
+ pu_nscd_ttl);
+ }
+ (void) mutex_unlock(&activity_lock);
+ }
+
+ /* no activity in the specified seconds, exit and disconnect */
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no activity in the last %d seconds, exit\n", pu_nscd_ttl);
+ exit(0);
+}
+
+void
+_nscd_proc_fork(
+ void *buf,
+ int iam)
+{
+ int slot;
+ int ret;
+ char *fmri;
+ pid_t cid;
+ uid_t set2uid;
+ gid_t set2gid;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_proc_fork";
+ nscd_fork_t *f;
+ nscd_imhere_t ih;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%d receives fork request from %d\n", _whoami, iam);
+
+ /* only main nscd sends fork requests */
+ if (iam != NSCD_MAIN) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n",
+ iam);
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_MAIN_IMPOSTER);
+ }
+
+ /* only forker handles fork requests */
+ if (_whoami != NSCD_FORKER) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "MAIN IMPOSTER CAUGHT! I AM NOT FORKER!\n");
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_WRONG_NSCD);
+ }
+
+ /* fork a child for the slot assigned by the main nscd */
+ f = NSCD_N2N_DOOR_DATA(nscd_fork_t, buf);
+ slot = f->slot;
+ /* set the uid/gid as assigned by the main nscd */
+ set2uid = f->uid;
+ set2gid = f->gid;
+
+ /* ignore bad slot number */
+ if (slot < 0 || slot >= max_pu_nscd) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "bas slot number\n");
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
+ }
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "before fork1() ...\n");
+
+ if ((cid = fork1()) == 0) {
+ _whoami = NSCD_CHILD;
+
+ /* close all except the log file */
+ if (_logfd > 0) {
+ int i;
+ for (i = 0; i < _logfd; i++)
+ (void) close(i);
+ closefrom(_logfd + 1);
+ } else
+ closefrom(0);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "child %d\n", getpid());
+
+ (void) setgid(set2gid);
+ (void) setuid(set2uid);
+
+ /* set up the door and server thread pool */
+ if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1)
+ exit(-1);
+
+ /* tell libsldap to do self cred only */
+ (void) setup_ldap_backend();
+
+ /* notify main that child is active */
+ ih.slot = slot;
+ for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
+ ret = _nscd_doorcall_sendfd(_doorfd,
+ NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI),
+ &ih, sizeof (ih), NULL);
+
+ NSCD_RETURN_STATUS_SUCCESS(phdr);
+ } if (cid == (pid_t)-1) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "forker unable to fork ...\n");
+
+ /* enter the maintenance mode */
+ if ((fmri = getenv("SMF_FMRI")) != NULL) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "entering maintenance mode ...\n");
+ smf_maintain_instance(fmri, SMF_TEMPORARY);
+ }
+ exit(0);
+ } else {
+ /*
+ * start the monitor so as to exit as early as
+ * possible if no other processes are running
+ * with the same PUN uid (i.e., this PUN is
+ * not needed any more)
+ */
+ (void) init_user_proc_monitor();
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "child forked: parent pid = %d, child pid = %d\n",
+ getpid(), cid);
+
+ NSCD_SET_STATUS_SUCCESS(phdr);
+ }
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "after fork\n");
+}
+
+static void
+selfcred_fork(
+ void *buf,
+ int doorfd,
+ int cslot,
+ uid_t uid,
+ gid_t gid)
+{
+ int ret;
+ nscd_fork_t f;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "selfcred_fork";
+
+ /* if no door fd, do nothing */
+ if (doorfd == -1) {
+ NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NO_DOOR);
+ }
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "sending fork request to door %d for slot %d "
+ "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid);
+
+ f.slot = cslot;
+ f.uid = uid;
+ f.gid = gid;
+
+ ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI),
+ &f, sizeof (f), NULL, 0, phdr);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "fork request sent to door %d for slot %d (rc = %d)\n",
+ doorfd, cslot, ret);
+
+ if (NSCD_STATUS_IS_NOT_OK(phdr)) {
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "fork request sent to door %d for slot %d failed: "
+ "status = %d, errno = %s, nscd status = %d\n", doorfd,
+ cslot, NSCD_GET_STATUS(phdr), strerror(NSCD_GET_ERRNO(phdr)),
+ NSCD_GET_NSCD_STATUS(phdr));
+
+ }
+}
+
+void
+_nscd_proc_alt_get(
+ void *buf,
+ int *door)
+{
+ int errnum;
+ uid_t set2uid;
+ gid_t set2gid;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_proc_alt_get";
+ ucred_t *uc = NULL;
+ child_t *ch;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getting an alternate door ...\n");
+
+ /* make sure there is a door to talk to the forker */
+ if (forking_door == -1) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
+ (me, "no door to talk to the forker\n");
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NO_FORKER);
+ }
+
+ /* get door client's credential information */
+ if (door_ucred(&uc) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred failed: %s\n", strerror(errnum));
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
+ NSCD_DOOR_UCRED_ERROR);
+ }
+
+ /* get door client's effective uid and effective gid */
+ set2uid = ucred_geteuid(uc);
+ set2gid = ucred_getegid(uc);
+ ucred_free(uc);
+ uc = NULL;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "child uid = %d, gid = %d\n", set2uid, set2gid);
+
+ /* is a slot available ? if not, no one to serve */
+ if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) {
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no child slot available (child array = %p, slot = %d)\n",
+ child, ch->child_slot);
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NO_CHILD_SLOT);
+ }
+
+ /* create the per user nscd if necessary */
+ if (ch->child_state != CHILD_STATE_PIDKNOWN) {
+
+ nss_pheader_t phdr1;
+ NSCD_CLEAR_STATUS(&phdr1);
+
+ (void) mutex_lock(ch->mutex);
+ if (ch->child_state == CHILD_STATE_UIDKNOWN) {
+
+ /* ask forker to fork a new child */
+ selfcred_fork(&phdr1, forking_door, ch->child_slot,
+ set2uid, set2gid);
+ if (NSCD_STATUS_IS_NOT_OK(&phdr1)) {
+ (void) mutex_unlock(ch->mutex);
+ NSCD_COPY_STATUS(phdr, &phdr1);
+ return;
+ }
+ ch->child_state = CHILD_STATE_FORKSENT;
+ }
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n",
+ ch->child_slot, set2uid, set2gid);
+
+ /* wait for the per user nscd to become available */
+ while (ch->child_state == CHILD_STATE_FORKSENT) {
+ timestruc_t to;
+ int err;
+ int ttl = 5;
+
+ to.tv_sec = ttl;
+ to.tv_nsec = 0;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "cond_reltimedwait %d seconds\n", ttl);
+ err = cond_reltimedwait(ch->cond, ch->mutex, &to);
+ if (err == ETIME) {
+ ch->child_state =
+ CHILD_STATE_UIDKNOWN;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "door wait timedout (slot = %d)\n",
+ ch->child_slot);
+ break;
+ }
+ }
+ (void) mutex_unlock(ch->mutex);
+ }
+
+ if (ch->child_state != CHILD_STATE_PIDKNOWN) {
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_INVALID_SLOT_STATE);
+ }
+
+ *door = ch->child_door;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "returning door %d for slot %d, uid %d, gid = %d\n",
+ *door, ch->child_slot, set2uid, set2gid);
+
+ NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0);
+}
+
+static char **
+cpargv(
+ int argc,
+ char **inargv)
+{
+ char **newargv;
+ int c = 4;
+ int i = 0, j, k = 0, n = 0;
+
+ newargv = (char **)calloc(c + 1, sizeof (char *));
+ if (newargv == NULL)
+ return (NULL);
+
+ newargv[n] = strdup(inargv[0]);
+ if (newargv[n++] == NULL) {
+ free(newargv);
+ return (NULL);
+ }
+
+ newargv[n] = strdup("-F");
+ if (newargv[n++] == NULL) {
+ free(newargv[0]);
+ free(newargv);
+ return (NULL);
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(inargv[i], "-f") == 0)
+ k = 2;
+ if (k == 0)
+ continue;
+
+ newargv[n] = strdup(inargv[i]);
+ if (newargv[n] == NULL) {
+ for (j = 0; j < n; j++)
+ free(newargv[j]);
+ free(newargv);
+ return (NULL);
+ }
+
+ k--;
+ n++;
+ }
+ return (newargv);
+}
+
+
+void
+_nscd_start_forker(
+ char *path,
+ int argc,
+ char **argv)
+{
+ pid_t cid;
+ struct rlimit rl;
+ char *me = "_nscd_start_forker";
+
+ /* if self cred is not configured, do nothing */
+ if (!_nscd_is_self_cred_on(1, NULL))
+ return;
+
+ /* save pathname and generate the new argv for the forker */
+ execpath = strdup(path);
+ execargv = cpargv(argc, argv);
+ if (execpath == NULL || execargv == NULL)
+ exit(1);
+
+ switch (cid = fork1()) {
+ case (pid_t)-1:
+ exit(1);
+ break;
+ case 0:
+ /* start the forker nscd */
+ (void) execv(path, execargv);
+ exit(0);
+ break;
+ default:
+ /* main nscd */
+ /* remember process id of the forker */
+ forker_pid = cid;
+
+ /* set NOFILE to unlimited */
+ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "Cannot set open file limit: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ /* enable child nscd management */
+ (void) _nscd_init_cslots();
+ break;
+ }
+}
+
+static nscd_rc_t
+get_ldap_funcs(
+ char *name,
+ void **func_p)
+{
+ char *me = "get_ldap_funcs";
+ static void *handle = NULL;
+ void *sym;
+
+ if (name == NULL && handle != NULL) {
+ (void) dlclose(handle);
+ return (NSCD_SUCCESS);
+ }
+ /* no handle to close, it's OK */
+ if (name == NULL)
+ return (NSCD_SUCCESS);
+
+ if (handle == NULL) {
+ handle = dlopen("libsldap.so.1", RTLD_LAZY);
+ if (handle == NULL) {
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to dlopen libsldap.so.1");
+ return (NSCD_CFG_DLOPEN_ERROR);
+ }
+ }
+
+ if ((sym = dlsym(handle, name)) == NULL) {
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to find symbol %s", name);
+ return (NSCD_CFG_DLSYM_ERROR);
+ } else
+ (void) memcpy(func_p, &sym, sizeof (void *));
+
+ return (NSCD_SUCCESS);
+}
+
+
+int
+_nscd_is_self_cred_on(int recheck, char **dblist)
+{
+ static int checked = 0;
+ static int is_on = 0;
+ static int (*ldap_func)();
+ char *srcs = "ldap"; /* only ldap support self cred */
+ int ldap_on = 0;
+
+ char *ldap_sc_func = "__ns_ldap_self_gssapi_config";
+ ns_ldap_self_gssapi_config_t ldap_config;
+
+ if (checked && !recheck) {
+ if (is_on && dblist != NULL)
+ *dblist = selfcred_dbs;
+ return (is_on);
+ }
+
+ if (selfcred_dbs != NULL)
+ free(selfcred_dbs);
+ selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs);
+
+ /*
+ * also check the ldap backend to see if
+ * the configuration there is good for
+ * doing self credentialing
+ */
+ if (ldap_func == NULL)
+ (void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
+ if (ldap_func != NULL) {
+ if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS &&
+ ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
+ ldap_on = 1;
+ }
+
+ is_on = pu_nscd_enabled == nscd_true &&
+ ldap_on && selfcred_dbs != NULL;
+
+ checked = 1;
+
+ if (is_on && dblist != NULL)
+ *dblist = selfcred_dbs;
+
+ return (is_on);
+}
+
+static nscd_rc_t
+setup_ldap_backend()
+{
+ nscd_rc_t rc;
+ static void (*ldap_func)();
+ char *ldap_sc_func = "__ns_ldap_self_gssapi_only_set";
+ if (ldap_func == NULL)
+ rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
+ if (ldap_func != NULL) {
+ ldap_func(1);
+ return (NSCD_SUCCESS);
+ }
+ return (rc);
+}
+
+/*ARGSUSED*/
+void
+_nscd_peruser_getadmin(
+ void *buf,
+ int buf_size)
+{
+ void *result_mn = NSCD_N2N_DOOR_DATA(void, buf);
+ int errnum = 0;
+ int ret;
+ uid_t uid;
+ nss_pheader_t *phdr = (nss_pheader_t *)buf;
+ char *me = "_nscd_peruser_getadmin";
+ ucred_t *uc = NULL;
+ child_t *ch;
+
+ /* get door client's credential information */
+ if (door_ucred(&uc) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "door_ucred failed: %s\n", strerror(errnum));
+
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
+ NSCD_DOOR_UCRED_ERROR);
+ }
+
+ /* get door client's effective uid */
+ uid = ucred_geteuid(uc);
+ ucred_free(uc);
+ uc = NULL;
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "per user get admin ... (uid = %d)\n", uid);
+
+ /* is the per-user nscd running ? if not, no one to serve */
+ ch = get_cslot(uid, 1);
+ if (ch == NULL) {
+ NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
+ NSCD_SELF_CRED_NO_CHILD_SLOT);
+ }
+
+ ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN,
+ NULL, sizeof (nscd_admin_t), result_mn,
+ sizeof (nscd_admin_t), phdr);
+
+ if (ret == NSS_SUCCESS) {
+ phdr->data_len = sizeof (nscd_admin_t);
+ return;
+ }
+}
+
+static void
+set_selfcred_cfg(
+ char param,
+ void *data)
+{
+ int64_t prop_int;
+ char *me = "set_selfcred_cfg";
+
+ if (param == 'a' || param == 'e') {
+ pu_nscd_enabled = *(uint8_t *)get_smf_prop(
+ "enable_per_user_lookup", 'b', data);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "self cred config: enabled = %d\n", pu_nscd_enabled);
+ }
+
+ if (param == 'a' || param == 't') {
+ prop_int = *(int *)data;
+ pu_nscd_ttl = *(int64_t *)get_smf_prop(
+ "per_user_nscd_time_to_live", 'i', &prop_int);
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl);
+ }
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_selfcred_notify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void *cookie)
+{
+
+ nscd_cfg_global_selfcred_t *sc_cfg = &nscd_selfcred_cfg_g;
+ int off;
+
+ /*
+ * At init time, the whole group of config params are received.
+ * At update time, group or individual parameter value could
+ * be received.
+ */
+
+ if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
+
+ *sc_cfg = *(nscd_cfg_global_selfcred_t *)data;
+
+ off = offsetof(nscd_cfg_global_selfcred_t,
+ enable_selfcred);
+ set_selfcred_cfg('e', (char *)data + off);
+
+ off = offsetof(nscd_cfg_global_selfcred_t,
+ max_per_user_nscd);
+ set_selfcred_cfg('n', (char *)data + off);
+
+ off = offsetof(nscd_cfg_global_selfcred_t,
+ per_user_nscd_ttl);
+ set_selfcred_cfg('t', (char *)data + off);
+
+ return (NSCD_SUCCESS);
+ }
+
+ /*
+ * individual config parameter
+ */
+ off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred);
+ if (pdesc->p_offset == off) {
+ sc_cfg->enable_selfcred = *(nscd_bool_t *)data;
+ set_selfcred_cfg('e', data);
+ return (NSCD_SUCCESS);
+ }
+
+ off = offsetof(nscd_cfg_global_selfcred_t, max_per_user_nscd);
+ if (pdesc->p_offset == off) {
+ sc_cfg->max_per_user_nscd = *(int *)data;
+ set_selfcred_cfg('n', data);
+ return (NSCD_SUCCESS);
+ }
+
+ off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl);
+ if (pdesc->p_offset == off) {
+ sc_cfg->per_user_nscd_ttl = *(int *)data;
+ set_selfcred_cfg('t', data);
+ return (NSCD_SUCCESS);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_selfcred_verify(
+ void *data,
+ struct nscd_cfg_param_desc *pdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t dflag,
+ nscd_cfg_error_t **errorp,
+ void **cookie)
+{
+
+ return (NSCD_SUCCESS);
+}
+
+/* ARGSUSED */
+nscd_rc_t
+_nscd_cfg_selfcred_get_stat(
+ void **stat,
+ struct nscd_cfg_stat_desc *sdesc,
+ nscd_cfg_id_t *nswdb,
+ nscd_cfg_flag_t *dflag,
+ void (**free_stat)(void *stat),
+ nscd_cfg_error_t **errorp)
+{
+ return (NSCD_SUCCESS);
+}
+
+static int
+check_uid(char *pid_name)
+{
+ char pname[PATH_MAX];
+ static pid_t pid = 0;
+ static uid_t uid = 0;
+ static uid_t euid = 0;
+ int pfd; /* file descriptor for /proc/<pid>/psinfo */
+ psinfo_t info; /* process information from /proc */
+
+ if (uid == 0) {
+ pid = getpid();
+ uid = getuid();
+ euid = geteuid();
+ }
+
+ (void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name);
+retry:
+ if ((pfd = open(pname, O_RDONLY)) == -1) {
+ /* Process may have exited */
+ return (1);
+ }
+
+ /*
+ * Get the info structure for the process and close quickly.
+ */
+ if (read(pfd, (char *)&info, sizeof (info)) < 0) {
+ int saverr = errno;
+
+ (void) close(pfd);
+ if (saverr == EAGAIN)
+ goto retry;
+ if (saverr != ENOENT)
+ return (1);
+ }
+ (void) close(pfd);
+
+ if (info.pr_pid != pid &&
+ info.pr_uid == uid && info.pr_euid == euid)
+ return (0);
+ else
+ return (1);
+}
+
+
+/*
+ * FUNCTION: check_user_process
+ */
+/*ARGSUSED*/
+static void *
+check_user_process(void *arg)
+{
+
+ DIR *dp;
+ struct dirent *ep;
+ int found;
+ char *me = "check_user_process";
+
+ /*CONSTCOND*/
+ while (1) {
+ (void) sleep(60);
+
+ found = 0;
+
+ /*
+ * search the /proc directory and look at each process
+ */
+ if ((dp = opendir("/proc")) == NULL) {
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to open the /proc directory\n");
+ continue;
+ }
+
+ /* for each active process */
+ while (ep = readdir(dp)) {
+ if (ep->d_name[0] == '.') /* skip . and .. */
+ continue;
+ if (check_uid(ep->d_name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ /*
+ * if no process running as the PUN uid found, exit
+ * to kill this PUN
+ */
+ if (found == 0) {
+ (void) closedir(dp);
+ exit(1);
+ }
+ (void) closedir(dp);
+ }
+ /* NOTREACHED */
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
+}
+
+static nscd_rc_t
+init_user_proc_monitor() {
+
+ int errnum;
+ char *me = "init_user_proc_monitor";
+
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing the user process monitor\n");
+
+ /*
+ * start a thread to make sure there is at least a process
+ * running as the PUN user. If not, terminate this PUN.
+ */
+ if (thr_create(NULL, NULL, check_user_process,
+ NULL, THR_DETACHED, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create: %s\n", strerror(errnum));
+ return (NSCD_THREAD_CREATE_ERROR);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+static void *
+get_smf_prop(const char *var, char type, void *def_val)
+{
+ scf_simple_prop_t *prop;
+ void *val = def_val;
+ char *me = "get_smf_prop";
+
+ prop = scf_simple_prop_get(NULL, NULL, "config", var);
+ if (prop) {
+ switch (type) {
+ case 'b':
+ val = scf_simple_prop_next_boolean(prop);
+ break;
+
+ case 'i':
+ val = scf_simple_prop_next_integer(prop);
+ break;
+
+ case 'c':
+ val = scf_simple_prop_next_count(prop);
+ break;
+ }
+ scf_simple_prop_free(prop);
+ }
+
+ if (prop == NULL || val == NULL) {
+ char vs[64];
+
+ switch (type) {
+ case 'b':
+ if (*(uint8_t *)def_val)
+ (void) strcpy(vs, "yes");
+ else
+ (void) strcpy(vs, "no");
+
+ break;
+
+ case 'i':
+ case 'c':
+ (void) sprintf(vs, "%lld", *(int64_t *)def_val);
+ break;
+
+ }
+ _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT)
+ (me, "no value for config/%s (%s). "
+ "Using default \"%s\"\n", var,
+ scf_strerror(scf_error()), vs);
+ }
+
+ return (val);
+}
diff --git a/usr/src/cmd/nscd/nscd_selfcred.h b/usr/src/cmd/nscd/nscd_selfcred.h
new file mode 100644
index 0000000000..6a42c226e4
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_selfcred.h
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_SELFCRED_H
+#define _NSCD_SELFCRED_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <unistd.h>
+#include <door.h>
+#include "nscd_door.h"
+
+/*
+ * structure used for door call NSCD_IMHERE
+ */
+typedef struct nscd_imhere {
+ int slot;
+} nscd_imhere_t;
+
+/*
+ * structure used for door call NSCD_FORK
+ */
+typedef struct nscd_fork {
+ int slot;
+ uid_t uid;
+ gid_t gid;
+} nscd_fork_t;
+
+/*
+ * prototypes
+ */
+int _nscd_is_self_cred_on(int recheck, char **dblist);
+void _nscd_set_forker_pid(pid_t pid);
+void _nscd_free_cslots();
+void _nscd_kill_forker();
+void _nscd_kill_all_children();
+void _nscd_proc_iamhere(void *buf, door_desc_t *dp,
+ uint_t n_desc, int iam);
+void _nscd_proc_pulse(void *buf, int iam);
+void _nscd_proc_fork(void *buf, int iam);
+void _nscd_proc_alt_get(void *buf, int *door);
+void _nscd_start_forker(char *path, int argc, char **argv);
+void _nscd_peruser_getadmin(void *buf, int buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_SELFCRED_H */
diff --git a/usr/src/cmd/nscd/nscd_seqnum.c b/usr/src/cmd/nscd/nscd_seqnum.c
new file mode 100644
index 0000000000..bf1c1d9e39
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_seqnum.c
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "nscd_db.h"
+
+static nscd_seq_num_t acc_seq = 1;
+static mutex_t seq_mutex = DEFAULTMUTEX;
+static nscd_cookie_t cookie = 1234;
+static mutex_t cookie_mutex = DEFAULTMUTEX;
+
+nscd_seq_num_t
+_nscd_get_seq_num()
+{
+ nscd_seq_num_t seq_num;
+
+ (void) mutex_lock(&seq_mutex);
+ seq_num = acc_seq;
+ acc_seq += 1;
+ (void) mutex_unlock(&seq_mutex);
+
+ return (seq_num);
+}
+
+nscd_cookie_t
+_nscd_get_cookie()
+{
+ nscd_cookie_t ret;
+
+ (void) mutex_lock(&cookie_mutex);
+ ret = cookie;
+ cookie += 1;
+ (void) mutex_unlock(&cookie_mutex);
+
+ return (ret);
+}
diff --git a/usr/src/cmd/nscd/nscd_smfmonitor.c b/usr/src/cmd/nscd/nscd_smfmonitor.c
new file mode 100644
index 0000000000..ab6c647083
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_smfmonitor.c
@@ -0,0 +1,209 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <libscf.h>
+#include <string.h>
+#include "nscd_switch.h"
+#include "nscd_log.h"
+#include "nscd_door.h"
+
+extern int _whoami;
+
+/*
+ * Service states monitored by nscd. Protected by
+ * readers/writer lock nscd_smf_service_state_lock
+ */
+nscd_smf_state_t *nscd_smf_service_state;
+static rwlock_t nscd_smf_service_state_lock = DEFAULTRWLOCK;
+/*
+ * init service state table
+ */
+nscd_rc_t
+_nscd_alloc_service_state_table()
+{
+ int i;
+
+ nscd_smf_service_state = calloc(NSCD_NUM_SMF_FMRI,
+ sizeof (nscd_smf_state_t));
+
+ if (nscd_smf_service_state == NULL)
+ return (NSCD_NO_MEMORY);
+
+ for (i = 1; i < NSCD_NUM_SMF_FMRI; i++)
+ NSCD_SMF_SVC_STATE(i) = NSCD_SVC_STATE_UNINITED;
+
+ return (NSCD_SUCCESS);
+}
+
+static int
+query_smf_state(int srci)
+{
+
+ int ret = NSCD_SVC_STATE_UNINITED;
+ char *state = NULL;
+ char *me = "query_smf_state";
+
+ state = smf_get_state(NSCD_SMF_SVC_FMRI(srci));
+ if (state == NULL)
+ return (ret);
+
+ _NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
+ (me, "%s -- %s\n", state, NSCD_SMF_SVC_FMRI(srci));
+
+ (void) rw_wrlock(&nscd_smf_service_state_lock);
+
+ if (nscd_smf_service_state[srci].src_name == NULL)
+ nscd_smf_service_state[srci].src_name =
+ NSCD_NSW_SRC_NAME(srci);
+
+ if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_UNINIT;
+ else if (strcmp(state, SCF_STATE_STRING_MAINT) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_MAINT;
+ else if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_OFFLINE;
+ else if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DISABLED;
+ else if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_ONLINE;
+ else if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)
+ NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DEGRADED;
+
+ ret = NSCD_SMF_SVC_STATE(srci);
+ (void) rw_unlock(&nscd_smf_service_state_lock);
+
+ free(state);
+ return (ret);
+}
+
+/* ARGSUSED */
+static void *
+set_smf_state(void *arg)
+{
+
+ int i;
+ int st;
+
+ /*
+ * the forker nscd needs not monitor the state
+ * of the client services
+ */
+ if (_whoami == NSCD_FORKER)
+ thr_exit(0);
+
+ /*CONSTCOND*/
+ while (1) {
+
+ /* skip the first service which is nscd */
+ for (i = 1; i < NSCD_NUM_SMF_FMRI; i++) {
+ st = query_smf_state(i);
+ if (st == NSCD_SVC_STATE_UNINITED)
+ break;
+ }
+
+ (void) sleep(NSCD_SW_CFG_G.check_smf_state_interval_g);
+ }
+ /* NOTREACHED */
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
+}
+
+nscd_rc_t
+_nscd_init_smf_monitor() {
+
+ int errnum;
+ char *me = "_nscd_init_smf_monitor";
+
+ _NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initializing the smf monitor\n");
+
+ /*
+ * start a thread to check the state of the client services
+ */
+ if (thr_create(NULL, NULL, set_smf_state,
+ NULL, THR_DETACHED, NULL) != 0) {
+ errnum = errno;
+ _NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_ERROR)
+ (me, "thr_create: %s\n", strerror(errnum));
+ return (NSCD_THREAD_CREATE_ERROR);
+ }
+
+ return (NSCD_SUCCESS);
+}
+
+int
+_nscd_get_smf_state(int srci, int dbi, int recheck)
+{
+ int s;
+ char *n;
+
+ n = NSCD_NSW_SRC_NAME(srci);
+
+ /* the files, compat, and dns backends are always available */
+ if ((*n == 'f' || *n == 'c' || *n == 'd') &&
+ (strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 ||
+ strcmp(NSCD_NSW_SRC_NAME(srci), "compat") == 0 ||
+ strcmp(NSCD_NSW_SRC_NAME(srci), "dns") == 0)) {
+ return (SCF_STATE_ONLINE);
+ }
+
+ /*
+ * for the printer database and user backend, treat the
+ * backend as a unsupported one, as nscd can not access
+ * the home directory of the user
+ */
+ if (*n == 'u' && strcmp(NSCD_NSW_SRC_NAME(srci), "user") == 0) {
+ if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_PRINTERS) == 0)
+ return (NSCD_SVC_STATE_UNKNOWN_SRC);
+ else
+ return (SCF_STATE_ONLINE);
+ }
+
+ /*
+ * unknown backend is not supported by nscd,
+ * tell the switch engine to return NSS_TRYLOCAL
+ * via rc NSCD_SVC_STATE_UNKNOWN_SRC
+ */
+ if (srci >= _nscd_cfg_num_nsw_src)
+ return (NSCD_SVC_STATE_UNKNOWN_SRC);
+
+ if (recheck == 1)
+ return (query_smf_state(srci));
+
+ (void) rw_rdlock(&nscd_smf_service_state_lock);
+ s = NSCD_SMF_SVC_STATE(srci);
+ (void) rw_unlock(&nscd_smf_service_state_lock);
+
+ /*
+ * if the state has been queried at least once but is
+ * still not online, query one more time
+ */
+ if (s != NSCD_SVC_STATE_UNINITED && s < SCF_STATE_ONLINE)
+ s = query_smf_state(srci);
+
+ return (s);
+}
diff --git a/usr/src/cmd/nscd/nscd_switch.c b/usr/src/cmd/nscd/nscd_switch.c
new file mode 100644
index 0000000000..351b6ad03e
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_switch.c
@@ -0,0 +1,1546 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h> /* getenv() */
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <nss_dbdefs.h>
+#include <exec_attr.h>
+#include <gssapi/gssapi.h>
+#include "nscd_door.h"
+#include "nscd_switch.h"
+#include "nscd_log.h"
+#include "nscd_frontend.h"
+
+#pragma weak nss_search = _nss_search
+#define nss_search _nss_search
+
+extern rwlock_t nscd_smf_service_state_lock;
+
+/* nscd id: main, forker, or child */
+extern int _whoami;
+
+static int
+retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp)
+{
+ if (res != NSS_TRYAGAIN && res != NSS_NISSERVDNS_TRYAGAIN) {
+ if (res == NSS_SUCCESS) {
+ __NSW_UNPAUSE_ACTION(lkp->actions[__NSW_TRYAGAIN]);
+ __NSW_UNPAUSE_ACTION(
+ lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]);
+ }
+ return (0);
+ }
+
+ if ((res == NSS_TRYAGAIN &&
+ lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER) ||
+ (res == NSS_NISSERVDNS_TRYAGAIN &&
+ lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER))
+ return (1);
+
+ if (res == NSS_TRYAGAIN &&
+ lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
+ if (n <= lkp->max_retries)
+ return (1);
+ else {
+ lkp->actions[__NSW_TRYAGAIN] = __NSW_TRYAGAIN_PAUSED;
+ return (0);
+ }
+
+ if (res == NSS_NISSERVDNS_TRYAGAIN &&
+ lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
+ if (n <= lkp->max_retries)
+ return (1);
+ else {
+ lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] =
+ __NSW_TRYAGAIN_PAUSED;
+ return (0);
+ }
+
+ return (0);
+}
+
+static thread_key_t loopback_key;
+static mutex_t loopback_key_lock = DEFAULTMUTEX;
+static int loopback_key_created = 0;
+typedef struct lb_key {
+ int srci;
+ int dbi;
+ int fnum;
+ int *lb_flagp;
+} lb_key_t;
+
+static int
+set_loopback_key(lb_key_t *key) {
+
+ int rc = 0;
+ lb_key_t *k;
+
+ if (!loopback_key_created) {
+ (void) mutex_lock(&loopback_key_lock);
+ if (!loopback_key_created) {
+ if ((rc = thr_keycreate(&loopback_key,
+ NULL)) == 0)
+ loopback_key_created = 1;
+ }
+ (void) mutex_unlock(&loopback_key_lock);
+ }
+ if (rc == 0) {
+ /* set key if not already set */
+ if (thr_getspecific(loopback_key, (void **)&k) == 0 &&
+ k == NULL) {
+ rc = thr_setspecific(loopback_key, key);
+ }
+ }
+
+ return (rc);
+}
+
+static lb_key_t *
+get_loopback_key(void) {
+
+ char *me = "get_loopback_key";
+ int rc = 0;
+ lb_key_t *k = NULL;
+
+ if (!loopback_key_created)
+ return (NULL);
+
+ rc = thr_getspecific(loopback_key, (void **)&k);
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "get loopback key rc= %d, key = %p\n", rc, k);
+
+ if (rc == 0 && k != NULL)
+ return (k);
+
+ return (NULL);
+}
+
+static void
+clear_loopback_key(lb_key_t *key) {
+
+ char *me = "clear_loopback_key";
+
+ if (loopback_key_created && key != 0) {
+ /*
+ * key->lb_flagp points to the location of the
+ * flag, check_flag, in the stack where it was
+ * first set; clearing the flag tells that
+ * stack the loopback error has been resolved
+ */
+ *key->lb_flagp = 0;
+ (void) thr_setspecific(loopback_key, NULL);
+ }
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "key %p cleared\n", key);
+}
+
+static thread_key_t initf_key;
+static mutex_t initf_key_lock = DEFAULTMUTEX;
+static int initf_key_created = 0;
+
+static int
+set_initf_key(void *pbuf) {
+
+ int rc = 0;
+
+ if (!initf_key_created) {
+ (void) mutex_lock(&initf_key_lock);
+ if (!initf_key_created) {
+ if ((rc = thr_keycreate(&initf_key, NULL)) == 0)
+ initf_key_created = 1;
+ }
+ (void) mutex_unlock(&initf_key_lock);
+ }
+ if (rc == 0)
+ rc = thr_setspecific(initf_key, pbuf);
+
+ return (rc);
+}
+
+static void *
+get_initf_key(void) {
+
+ char *me = "get_initf_key";
+ void *pbuf;
+ int rc = 0;
+
+ if (!initf_key_created)
+ return (NULL);
+
+ rc = thr_getspecific(initf_key, (void **)&pbuf);
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "got initf pbuf rc= %d, key = %p\n", rc, pbuf);
+
+ if (rc == 0 && pbuf != NULL)
+ return (pbuf);
+
+ return (NULL);
+}
+
+static void
+clear_initf_key(void) {
+
+ char *me = "clear_initf_key";
+
+ if (initf_key_created)
+ (void) thr_setspecific(initf_key, NULL);
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "initf pbuf cleared\n");
+}
+
+/*
+ * Call the input initf function to extract the
+ * NSS front end parameters and examine them to
+ * determine if an NSS lookup is to be performed
+ * on a regular or a pseudo (called from compat
+ * backend) database. Then set the necessary
+ * parameters for later data structures creation
+ * and processing.
+ */
+static nscd_rc_t
+getparams(
+ int search_fnum,
+ nss_db_initf_t initf,
+ nscd_nsw_params_t *params)
+{
+
+ nscd_rc_t rc = NSCD_SUCCESS;
+ nss_db_params_t *p;
+ int j;
+ char *dbn;
+ const char *n;
+
+ p = &params->p;
+ (void) memset(p, 0, sizeof (*p));
+ (*initf)(p);
+ params->dbi = -1;
+ params->cfgdbi = -1;
+ params->compati = -1;
+ params->dnsi = -1;
+
+ /* map database name to index */
+ n = p->name;
+ for (j = 0; j < NSCD_NUM_DB; j++) {
+ dbn = NSCD_NSW_DB_NAME(j);
+ if (*n != *dbn)
+ continue;
+ if (strcmp(n, dbn) == 0) {
+ params->dbi = j;
+ if (*n != 'h' && *n != 'i' && *n != 's' && *n != 'a')
+ break;
+ if (strcmp(n, NSS_DBNAM_HOSTS) == 0 &&
+ search_fnum == NSS_DBOP_HOSTS_BYNAME)
+ params->dnsi = 0;
+ else if (strcmp(n, NSS_DBNAM_IPNODES) == 0 &&
+ search_fnum == NSS_DBOP_IPNODES_BYNAME)
+ params->dnsi = 1;
+ else if (strcmp(n, NSS_DBNAM_SHADOW) == 0)
+ params->privdb = 1;
+ else if (strcmp(n, NSS_DBNAM_AUDITUSER) == 0)
+ params->privdb = 1;
+ break;
+ }
+ }
+
+ /*
+ * use the switch policy for passwd_compat or
+ * group_compat?
+ */
+ if (p->config_name != NULL) {
+
+ n = p->config_name;
+ for (j = 0; j < NSCD_NUM_DB; j++) {
+ dbn = NSCD_NSW_DB_NAME(j);
+ if (*n == *dbn) {
+ if (strcmp(n, dbn) == 0) {
+ params->cfgdbi = j;
+ break;
+ }
+ }
+ }
+ }
+
+ /* map the database name to the pseudo database index */
+ if (params->cfgdbi != -1) {
+ if (strstr(p->config_name, "_compat") != NULL) {
+ n = p->name;
+ for (j = params->cfgdbi; j < NSCD_NUM_DB; j++) {
+ dbn = NSCD_NSW_DB_NAME(j);
+ if (*n == *dbn) {
+ if (strcmp(n, dbn) == 0) {
+ params->compati = j;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ assert(params->dbi != -1);
+ return (rc);
+}
+
+static void
+nscd_initf(nss_db_params_t *p)
+{
+ nss_pheader_t *pbuf;
+ nssuint_t off;
+ nss_dbd_t *pdbd;
+ char *me = "nscd_initf";
+
+ pbuf = (nss_pheader_t *)get_initf_key();
+ if (pbuf == NULL) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "ERROR: initf key not set\n");
+ return;
+ }
+
+ if (pbuf->dbd_len <= sizeof (nss_dbd_t)) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid db front params data ? dbd_len = %d\n",
+ pbuf->dbd_len);
+ return;
+ }
+
+ off = pbuf->dbd_off;
+ pdbd = (nss_dbd_t *)((void *)((char *)pbuf + off));
+
+ p->name = (char *)pdbd + pdbd->o_name;
+ p->config_name = (char *)pdbd + pdbd->o_config_name;
+ p->default_config = (char *)pdbd + pdbd->o_default_config;
+ p->flags = (enum nss_dbp_flags)pdbd->flags;
+ (void) memcpy(&p->private, &pbuf->nscdpriv, sizeof (p->private));
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "db frontend params: name =%s, config_name = %s, "
+ "default_config = %s, flags = %x\n", p->name,
+ (p->config_name && *p->config_name != '\0' ?
+ p->config_name : "<NOT SPECIFIED>"),
+ (p->default_config && *p->default_config != '\0' ?
+ p->default_config : "<NOT SPECIFIED>"),
+ p->flags);
+}
+
+
+static void
+trace_result(
+ int dbi,
+ int srci,
+ int op,
+ nss_status_t res,
+ nss_XbyY_args_t *arg)
+{
+ char *res_str;
+ char *src = "?";
+ char *db = "?";
+ char *me = "nss_search";
+
+ switch (res) {
+ case NSS_SUCCESS:
+ res_str = "NSS_SUCCESS";
+ break;
+ case NSS_NOTFOUND:
+ res_str = "NSS_NOTFOUND";
+ break;
+ case NSS_UNAVAIL:
+ res_str = "NSS_UNAVAIL";
+ break;
+ case NSS_TRYAGAIN:
+ res_str = "NSS_TRYAGAIN";
+ break;
+ case NSS_NISSERVDNS_TRYAGAIN:
+ res_str = "NSS_NISSERVDNS_TRYAGAIN";
+ break;
+ default:
+ res_str = "UNKNOWN STATUS";
+ break;
+ }
+
+ if (dbi != -1)
+ db = NSCD_NSW_DB_NAME(dbi);
+ if (srci != -1)
+ src = NSCD_NSW_SRC_NAME(srci);
+
+ if (res == NSS_SUCCESS) {
+ _nscd_logit(me,
+"%s: database: %s, operation: %d, source: %s returned \"%s\", length = %d\n",
+ res_str, db, op, src, arg->buf.buffer, arg->returnlen);
+
+ return;
+ }
+
+ _nscd_logit(me,
+"%s: database: %s, operation: %d, source: %s, erange= %d, errno: %s \n",
+ res_str, db, op, src, arg->erange, strerror(arg->h_errno));
+}
+
+/*
+ * Determine if a request should be done locally in the getXbyY caller's
+ * process. Return none zero if yes, 0 otherwise.
+ * This function returnis 1 if:
+ * -- the database is exec_attr and the search_flag is GET_ALL
+ */
+static int
+try_local(
+ int dbi,
+ void *arg)
+{
+ struct nss_XbyY_args *ap = (struct nss_XbyY_args *)arg;
+ _priv_execattr *ep;
+ int rc = 0;
+ char *me = "try_local";
+
+ if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_EXECATTR) == 0) {
+ if ((ep = ap->key.attrp) != NULL &&
+ ep->search_flag == GET_ALL)
+ rc = 1;
+ }
+
+ if (rc != 0) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "TRYLOCAL: exec_attr:GET_ALL\n");
+ }
+
+ return (rc);
+}
+
+static nscd_rc_t
+get_dns_funcs(int dnsi, void **func_p)
+{
+ char *me = "get_dns_funcs";
+ static void *handle = NULL;
+ static mutex_t func_lock = DEFAULTMUTEX;
+ void *sym;
+ char *func_name[2] = { "_nss_get_dns_hosts_name",
+ "_nss_get_dns_ipnodes_name" };
+ static void *func[2] = {NULL, NULL};
+
+ if (handle != NULL && dnsi > 0 && func[dnsi] != NULL) {
+ (void) memcpy(func_p, &func[dnsi], sizeof (void *));
+ return (NSCD_SUCCESS);
+ }
+
+ (void) mutex_lock(&func_lock);
+
+ /* close the handle if requested */
+ if (dnsi < 0) {
+ if (handle != NULL) {
+ (void) dlclose(handle);
+ func[0] = NULL;
+ func[1] = NULL;
+ }
+ (void) mutex_unlock(&func_lock);
+ return (NSCD_SUCCESS);
+ }
+
+ if (handle != NULL && func[dnsi] != NULL) {
+ (void) memcpy(func_p, &func[dnsi], sizeof (void *));
+ (void) mutex_unlock(&func_lock);
+ return (NSCD_SUCCESS);
+ }
+
+ if (handle == NULL) {
+ handle = dlopen("nss_dns.so.1", RTLD_LAZY);
+ if (handle == NULL) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to dlopen nss_dns.so.1\n");
+ (void) mutex_unlock(&func_lock);
+ return (NSCD_CFG_DLOPEN_ERROR);
+ }
+ }
+
+ if ((sym = dlsym(handle, func_name[dnsi])) == NULL) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to find symbol %s\n", func_name[dnsi]);
+ (void) mutex_unlock(&func_lock);
+ return (NSCD_CFG_DLSYM_ERROR);
+ } else {
+ (void) memcpy(func_p, &sym, sizeof (void *));
+ (void) memcpy(&func[dnsi], &sym, sizeof (void *));
+ }
+
+ (void) mutex_unlock(&func_lock);
+ return (NSCD_SUCCESS);
+}
+
+static nss_status_t
+search_dns_withttl(nscd_sw_return_t *swret, char *srcname, int dnsi)
+{
+ nss_status_t (*func)();
+ nss_status_t res = NSS_UNAVAIL;
+ nscd_rc_t rc;
+
+ swret->noarg = 0;
+ if (strcmp(srcname, "dns") != 0)
+ return (NSS_ERROR);
+
+ rc = get_dns_funcs(dnsi, (void **)&func);
+ if (rc == NSCD_SUCCESS)
+ res = (func)(NULL, &swret->pbuf, &swret->pbufsiz);
+ return (res);
+}
+
+/*
+ * Returns a flag to indicate if needs to fall back to the
+ * main nscd when a per-user lookup failed with rc NSS_NOTFOUND.
+ */
+static int
+set_fallback_flag(char *srcname, nss_status_t rc)
+{
+ char *me = "set_fallback_flag";
+ if (strcmp(srcname, "ldap") == 0 && rc == NSS_NOTFOUND) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "NSS_NOTFOUND (ldap): fallback to main nscd "
+ "may be needed\n");
+ return (1);
+ }
+ return (0);
+}
+
+nss_status_t
+nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
+ void *search_args)
+{
+ char *me = "nss_search";
+ nss_status_t res = NSS_UNAVAIL;
+ nscd_nsw_state_t *s = NULL;
+ int n_src;
+ unsigned int status_vec = 0;
+ int dbi, srci = -1;
+ int check_loopback = 0;
+ int state_thr = 0;
+ lb_key_t key, *k = NULL;
+ nss_db_root_t root_db;
+ nscd_nsw_params_t params;
+ nscd_sw_return_t *swret;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "rootp = %p, initf = %p, search_fnum = %d, "
+ "search_args = %p\n", rootp, initf,
+ search_fnum, search_args);
+
+ NSCD_SW_STATS_G.lookup_request_received_g++;
+ NSCD_SW_STATS_G.lookup_request_in_progress_g++;
+ NSCD_SW_STATS_G.lookup_request_queued_g++;
+
+ /* determine db index, cfg db index, etc */
+ (void) getparams(search_fnum, initf, &params);
+ dbi = params.dbi;
+
+ /* get address of the switch engine return data area */
+ if (initf == nscd_initf) {
+ swret = (nscd_sw_return_t *)params.p.private;
+ swret->srci = -1;
+ } else {
+ swret = NULL;
+ params.dnsi = -1;
+ }
+
+ /*
+ * for request that should be processed by the client,
+ * send it back with status NSS_TRYLOCAL
+ */
+ if (try_local(dbi, search_args) == 1) {
+ res = NSS_TRYLOCAL;
+ goto error_exit;
+ }
+
+ NSCD_SW_STATS(dbi).lookup_request_received++;
+ NSCD_SW_STATS(dbi).lookup_request_in_progress++;
+ NSCD_SW_STATS(dbi).lookup_request_queued++;
+
+ /* if lookup not enabled, return NSS_UNAVAIL */
+ if (!(NSCD_SW_CFG_G.enable_lookup_g == nscd_true &&
+ NSCD_SW_CFG(dbi).enable_lookup == nscd_true)) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "lookup not enabled for %s\n", NSCD_NSW_DB_NAME(dbi));
+
+ goto error_exit;
+ }
+
+ /* determine if loopback checking is configured */
+ if (NSCD_SW_CFG_G.enable_loopback_checking_g == nscd_true &&
+ NSCD_SW_CFG(dbi).enable_loopback_checking == nscd_true) {
+ check_loopback = 1;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "loopback checking enabled for %s\n",
+ NSCD_NSW_DB_NAME(dbi));
+ }
+
+ if (check_loopback) {
+ k = get_loopback_key();
+ if (k != NULL) {
+ if (k->dbi != dbi || k->fnum != search_fnum) {
+ clear_loopback_key(k);
+ k = NULL;
+ }
+ }
+ }
+
+ if (s == 0) {
+ nscd_rc_t rc;
+
+ if (check_loopback) {
+ rc = _nscd_get_nsw_state_thread(&root_db, &params);
+ state_thr = 1;
+ } else
+ rc = _nscd_get_nsw_state(&root_db, &params);
+
+ NSCD_SW_STATS_G.lookup_request_queued_g--;
+ NSCD_SW_STATS(dbi).lookup_request_queued--;
+
+ if (rc != NSCD_SUCCESS)
+ goto error_exit;
+
+ s = (nscd_nsw_state_t *)root_db.s;
+ }
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "database = %s, config = [ %s ]\n", NSCD_NSW_DB_NAME(dbi),
+ (*s->nsw_cfg_p)->nsw_cfg_str);
+
+ for (n_src = 0; n_src < s->max_src; n_src++) {
+ nss_backend_t *be;
+ nss_backend_op_t funcp;
+ struct __nsw_lookup_v1 *lkp;
+ int smf_state;
+ int n_loop = 0;
+ int max_retry = 10;
+
+ res = NSS_UNAVAIL;
+
+ if (n_src == 0)
+ lkp = s->config->lookups;
+ else
+ lkp = lkp->next;
+
+ /* set the number of max. retries */
+ if (lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
+ max_retry = lkp->max_retries;
+
+ srci = (*s->nsw_cfg_p)->src_idx[n_src];
+ if (swret != NULL)
+ swret->srci = srci;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "nsw source = %s\n", NSCD_NSW_SRC_NAME(srci));
+
+ /* if no privilege to look up, skip */
+ if (params.privdb == 1 && swret != NULL &&
+ strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 &&
+ _nscd_get_client_euid() != 0) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "no privilege to look up, skip source\n");
+
+ goto next_src;
+ }
+
+ /* get state of the (backend) client service */
+ smf_state = _nscd_get_smf_state(srci, dbi, 0);
+
+ /* stop if the source is one that should be TRYLOCAL */
+ if (smf_state == NSCD_SVC_STATE_UNKNOWN_SRC) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "returning TRYLOCAL ... \n");
+ res = NSS_TRYLOCAL;
+ goto free_nsw_state;
+ }
+
+ if (check_loopback && k != NULL) {
+
+ if (k->srci == srci && k->dbi == dbi)
+ if (k->fnum == search_fnum) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "loopback detected: "
+ "source = %s, database = %s "
+ "search fnum = %d\n",
+ NSCD_NSW_SRC_NAME(srci),
+ NSCD_NSW_DB_NAME(dbi), search_fnum);
+
+ NSCD_SW_STATS_G.loopback_nsw_db_skipped_g++;
+ NSCD_SW_STATS(dbi).loopback_nsw_db_skipped++;
+ continue;
+ }
+ }
+
+ be = s->be[n_src];
+ if (be != NULL)
+ funcp = NSS_LOOKUP_DBOP(be, search_fnum);
+
+ if ((params.dnsi >= 0 && be == 0) || (params.dnsi < 0 &&
+ (be == 0 || (smf_state != NSCD_SVC_STATE_UNINITED &&
+ smf_state < SCF_STATE_ONLINE) || funcp == 0))) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "unable to look up source %s: be = %p, "
+ "smf state = %d, funcp = %p\n",
+ NSCD_NSW_SRC_NAME(srci), be, smf_state, funcp);
+
+ goto next_src;
+ }
+
+ do {
+ /*
+ * we can only retry max_retry times,
+ * otherwise threads may get stuck in this
+ * do-while loop forever
+ */
+ if (n_loop > max_retry) {
+ if (swret != NULL)
+ res = NSS_TRYLOCAL;
+ goto free_nsw_state;
+ }
+
+ /*
+ * set up to prevent loopback
+ */
+ if (check_loopback && k == NULL) {
+ key.srci = srci;
+ key.dbi = dbi;
+ key.fnum = search_fnum;
+ key.lb_flagp = &check_loopback;
+ (void) set_loopback_key(&key);
+ k = &key;
+ }
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "looking up source = %s, loop# = %d \n",
+ NSCD_NSW_SRC_NAME(srci), n_loop);
+
+ /*
+ * search the backend, if hosts lookups,
+ * try to get the hosts data with ttl first
+ */
+ if (params.dnsi >= 0) {
+ res = search_dns_withttl(swret,
+ NSCD_NSW_SRC_NAME(srci),
+ params.dnsi);
+ /*
+ * if not able to get ttl, fall back
+ * to the regular backend call
+ */
+ if (res == NSS_ERROR)
+ res = (*funcp)(be, search_args);
+ else {
+ /*
+ * status/result are in the
+ * packed buffer, not
+ * search_args
+ */
+ swret->noarg = 1;
+ }
+ } else
+ res = (*funcp)(be, search_args);
+ if (swret != NULL)
+ swret->errnum = errno;
+
+ /*
+ * backend is not up, check and update the
+ * smf state table
+ */
+ if (res == NSS_UNAVAIL)
+ (void) _nscd_get_smf_state(srci, dbi, 1);
+
+ /*
+ * may need to fall back to use the main nscd
+ * if per-user lookup
+ */
+ if (_whoami == NSCD_CHILD && swret != NULL)
+ swret->fallback = set_fallback_flag(
+ NSCD_NSW_SRC_NAME(srci), res);
+
+ _NSCD_LOG_IF(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG) {
+
+ /*
+ * set up to trace the result/status
+ * of the dns/ttl lookup
+ */
+ if (swret != NULL && swret->noarg == 1) {
+ nss_pheader_t *phdr;
+ struct nss_XbyY_args *arg;
+ arg = (struct nss_XbyY_args *)
+ search_args;
+ phdr = (nss_pheader_t *)swret->pbuf;
+ arg->buf.buffer = (char *)phdr +
+ phdr->data_off;
+ arg->returnlen = phdr->data_len;
+ if (phdr->p_errno == ERANGE)
+ arg->erange = 1;
+ arg->h_errno = phdr->p_herrno;
+ }
+
+ trace_result(dbi, srci, search_fnum, res,
+ (nss_XbyY_args_t *)search_args);
+ }
+
+ n_loop++;
+ } while (retry_test(res, n_loop, lkp));
+
+ next_src:
+
+ status_vec |= (1 << res);
+
+ if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) {
+ break;
+ }
+ }
+
+ free_nsw_state:
+
+ if (state_thr == 1)
+ _nscd_put_nsw_state_thread(s);
+ else
+ _nscd_put_nsw_state(s);
+ if (check_loopback && k != NULL)
+ clear_loopback_key(k);
+
+ if (res != NSS_SUCCESS)
+ goto error_exit;
+
+ NSCD_SW_STATS_G.lookup_request_succeeded_g++;
+ NSCD_SW_STATS(dbi).lookup_request_succeeded++;
+ NSCD_SW_STATS_G.lookup_request_in_progress_g--;
+ NSCD_SW_STATS(dbi).lookup_request_in_progress--;
+
+ return (NSS_SUCCESS);
+
+ error_exit:
+
+ NSCD_SW_STATS_G.lookup_request_failed_g++;
+ NSCD_SW_STATS_G.lookup_request_in_progress_g--;
+ NSCD_SW_STATS(dbi).lookup_request_failed++;
+ NSCD_SW_STATS(dbi).lookup_request_in_progress--;
+
+ return (res);
+}
+
+
+/* ===> get/set/endent */
+
+static void nss_setent_u(nss_db_root_t *,
+ nss_db_initf_t,
+ nss_getent_t *);
+static nss_status_t nss_getent_u(nss_db_root_t *,
+ nss_db_initf_t,
+ nss_getent_t *,
+ void *);
+static void nss_endent_u(nss_db_root_t *,
+ nss_db_initf_t,
+ nss_getent_t *);
+
+void
+nss_setent(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ if (contextpp == 0)
+ return;
+ nss_setent_u(rootp, initf, contextpp);
+}
+
+nss_status_t
+nss_getent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp,
+ void *args)
+{
+ nss_status_t status;
+
+ if (contextpp == 0) {
+ return (NSS_UNAVAIL);
+ }
+ status = nss_getent_u(rootp, initf, contextpp, args);
+ return (status);
+}
+
+void
+nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ if (contextpp == 0)
+ return;
+ nss_endent_u(rootp, initf, contextpp);
+}
+
+/*ARGSUSED*/
+static void
+end_iter_u(nss_db_root_t *rootp, struct nss_getent_context *contextp)
+{
+ nscd_getent_context_t *ctx;
+ nscd_nsw_state_t *s;
+ nss_backend_t *be;
+ int n_src;
+
+ ctx = (nscd_getent_context_t *)contextp;
+ s = ctx->nsw_state;
+ n_src = ctx->n_src;
+ be = ctx->be;
+
+ if (s != 0) {
+ if (n_src < s->max_src && be != 0) {
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
+ ctx->be = 0; /* Should be unnecessary, but hey */
+ }
+ }
+ ctx->n_src = 0;
+}
+
+static void
+nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ char *me = "nss_setent_u";
+ nscd_nsw_state_t *s;
+ nscd_getent_context_t *contextp;
+ nscd_nsw_params_t params;
+ nss_db_root_t root;
+ nss_backend_t *be;
+ int n_src, i;
+ nscd_sw_return_t *swret = NULL;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "rootp = %p, initf = %p, contextpp = %p \n",
+ rootp, initf, contextpp);
+
+ /* get the nsw db index via the initf function */
+ (void) getparams(-1, initf, &params);
+
+ /* get address of the switch engine return data area */
+ if (initf == nscd_initf)
+ swret = (nscd_sw_return_t *)params.p.private;
+
+ /* if no privilege to look up, return */
+ if (params.privdb == 1 && swret != NULL &&
+ ((nss_pheader_t *)(swret->pbuf))->p_euid != 0) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "no privilege \n");
+ return;
+ }
+
+ if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
+ if ((_nscd_get_getent_ctx(contextpp, &params)) !=
+ NSCD_SUCCESS) {
+ return;
+ }
+ contextp = (nscd_getent_context_t *)contextpp->ctx;
+ }
+ s = contextp->nsw_state;
+
+ if (s == 0) {
+ if (_nscd_get_nsw_state(&root, &params) !=
+ NSCD_SUCCESS) {
+ return;
+ }
+ s = (nscd_nsw_state_t *)root.s;
+ contextp->nsw_state = s;
+
+ } else {
+ s = contextp->nsw_state;
+ n_src = contextp->n_src;
+ be = contextp->be;
+ if (n_src == 0 && be != 0) {
+ /*
+ * Optimization: don't do endent, don't change
+ * backends, just do the setent. Look Ma, no locks
+ * (nor any context that needs updating).
+ */
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
+ return;
+ }
+ if (n_src < s->max_src && be != 0) {
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
+ contextp->be = 0; /* Play it safe */
+ }
+ }
+ for (n_src = 0, be = 0; n_src < s->max_src &&
+ (be = s->be[n_src]) == 0; n_src++) {
+ ;
+ }
+
+ contextp->n_src = n_src;
+ contextp->be = be;
+
+ if (be == 0) {
+ /* Things are broken enough that we can't do setent/getent */
+ nss_endent_u(rootp, initf, contextpp);
+ return;
+ }
+
+ /*
+ * make sure all the backends are supported
+ */
+ for (i = 0; i < s->max_src; i++) {
+ int st, srci;
+
+ srci = (*s->nsw_cfg_p)->src_idx[i];
+ st = _nscd_get_smf_state(srci, params.dbi, 1);
+ if (st == NSCD_SVC_STATE_UNKNOWN_SRC ||
+ st == NSCD_SVC_STATE_UNINITED) {
+ nss_endent_u(rootp, initf, contextpp);
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "backend (%s) not available (state = %d)\n",
+ NSCD_NSW_SRC_NAME(srci), st);
+
+ return;
+ }
+ }
+
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
+}
+
+nss_status_t
+nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp, void *args)
+{
+ char *me = "nss_getent_u";
+ nscd_nsw_state_t *s;
+ nscd_getent_context_t *contextp;
+ int n_src;
+ nss_backend_t *be;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "rootp = %p, initf = %p, contextpp = %p, args = %p\n",
+ rootp, initf, contextpp, args);
+
+ if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
+ nss_setent_u(rootp, initf, contextpp);
+ if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
+ /* Give up */
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_ERROR)
+ (me, "not able to obtain getent context ... give up\n");
+
+ return (NSS_UNAVAIL);
+ }
+ }
+
+ s = contextp->nsw_state;
+ n_src = contextp->n_src;
+ be = contextp->be;
+
+ if (s == 0) {
+ /*
+ * We've done an end_iter() and haven't done nss_setent()
+ * or nss_endent() since; we should stick in this state
+ * until the caller invokes one of those two routines.
+ */
+ return (NSS_SUCCESS);
+ }
+
+ while (n_src < s->max_src) {
+ nss_status_t res;
+ struct __nsw_lookup_v1 *lkp = NULL;
+ int n;
+
+ /* get the nsw config for the current source */
+ lkp = s->config->lookups;
+ for (n = 0; n < n_src; n++)
+ lkp = lkp->next;
+
+ if (be == 0) {
+ /* If it's null it's a bug, but let's play safe */
+ res = NSS_UNAVAIL;
+ } else {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "database: %s, backend: %s, nsswitch config: %s\n",
+ NSCD_NSW_DB_NAME(s->dbi),
+ lkp->service_name,
+ (*s->nsw_cfg_p)->nsw_cfg_str);
+
+ res = NSS_INVOKE_DBOP(be, NSS_DBOP_GETENT, args);
+ }
+
+ if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) {
+ if (res != __NSW_SUCCESS) {
+ end_iter_u(rootp,
+ (struct nss_getent_context *)contextp);
+ }
+ return (res);
+ }
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
+ do {
+ n_src++;
+ } while (n_src < s->max_src &&
+ (be = s->be[n_src]) == 0);
+ if (be == 0) {
+ /*
+ * This is the case where we failed to get the backend
+ * for the last source. We exhausted all sources.
+ */
+ nss_endent_u(rootp, initf, contextpp);
+ return (NSS_SUCCESS);
+ }
+ contextp->n_src = n_src;
+ contextp->be = be;
+ (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
+ }
+ /* Got to the end of the sources without finding another entry */
+ end_iter_u(rootp, (struct nss_getent_context *)contextp);
+ return (NSS_SUCCESS);
+ /* success is either a successful entry or end of the sources */
+}
+
+/*ARGSUSED*/
+void
+nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ char *me = "nss_endent_u";
+ nscd_getent_context_t *contextp;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "rootp = %p, initf = %p, contextpp = %p \n",
+ rootp, initf, contextpp);
+
+ if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
+ /* nss_endent() on an unused context is a no-op */
+ return;
+ }
+ end_iter_u(rootp, (struct nss_getent_context *)contextp);
+ _nscd_put_getent_ctx(contextp);
+ contextpp->ctx = NULL;
+}
+
+/*
+ * _nss_db_state_destr() and nss_delete() do nothing in nscd
+ * but is needed to make the caller (below nscd) happy
+ */
+/*ARGSUSED*/
+void
+_nss_db_state_destr(struct nss_db_state *s)
+{
+ /* nsw state in nscd is always reused, so do nothing here */
+}
+
+/*ARGSUSED*/
+void
+nss_delete(nss_db_root_t *rootp)
+{
+ /*
+ * the only resource kept tracked by the nss_db_root_t
+ * is the nsw state which is always reused and no need
+ * to be freed. So just return.
+ */
+}
+
+/*
+ * Start of nss_psearch/nss_psetent()/nss_pgetent()/nss_pendent()
+ * buffers switch entry points
+ */
+
+/*
+ * nss_psearch opens a packed structure header, assembles a local
+ * nss_XbyY_args_t structure and calls the local copy of nss_search.
+ * The return data is assembled in "files native format" in the
+ * return buffer location. Status if packed back up with the buffer
+ * and the whole wad is returned to the cache or the client.
+ */
+
+void
+nss_psearch(void *buffer, size_t length)
+{
+ /* inputs */
+ nss_db_initf_t initf;
+ int dbop;
+ int rc;
+ nss_XbyY_args_t arg;
+ nss_status_t status;
+ nscd_sw_return_t swret = { 0 }, *swrp = &swret;
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ char *me = "nss_psearch";
+
+ if (buffer == NULL || length == 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ status = nss_packed_arg_init(buffer, length,
+ NULL, &initf, &dbop, &arg);
+ if (status != NSS_SUCCESS) {
+ NSCD_RETURN_STATUS(pbuf, status, -1);
+ }
+
+ /*
+ * pass the address of the return data area
+ * for the switch engine to return its own data
+ */
+ (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp));
+ swret.pbuf = buffer;
+ swret.pbufsiz = length;
+
+ /*
+ * use the generic nscd_initf for all database lookups
+ * (the TSD key is the pointer to the packed header)
+ */
+ rc = set_initf_key(pbuf);
+ if (rc != 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL);
+ }
+ initf = nscd_initf;
+
+ /* Perform local search and pack results into return buffer */
+ /* nscd's search ignores db_root */
+ status = nss_search(NULL, initf, dbop, &arg);
+
+ /*
+ * If status is NSS_NOTFOUND and ldap also returned
+ * NSS_NOTFOUND, it is possible that the user does
+ * not have a credential, so check and see if
+ * needs to return NSS_ALTRETRY to let the main
+ * nscd get a chance to process the lookup
+ */
+ if (swret.fallback == 1 && status == NSS_NOTFOUND) {
+ OM_uint32 stat;
+
+ if (gss_inquire_cred(&stat, GSS_C_NO_CREDENTIAL,
+ NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "NSS_ALTRETRY: fallback to main nscd needed\n");
+
+ status = NSS_ALTRETRY;
+ }
+ }
+
+ NSCD_SET_STATUS(pbuf, status, -1);
+ errno = swret.errnum;
+
+ /*
+ * move result/status from args to packed buffer only if
+ * arg was being used
+ */
+ if (!swret.noarg)
+ nss_packed_set_status(buffer, length, status, &arg);
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "switch engine result: source is %s, status %d, "
+ "herrno is %d, errno is %s\n",
+ (swret.srci != -1) ? NSCD_NSW_SRC_NAME(swret.srci) : "<NOTSET>",
+ pbuf->p_status, pbuf->p_herrno, strerror(pbuf->p_errno));
+
+ /* clear the TSD key used by the generic initf */
+ clear_initf_key();
+ pbuf->nscdpriv = 0;
+}
+
+static void
+nscd_map_contextp(void *buffer, nss_getent_t *contextp,
+ nssuint_t **cookie_p, nssuint_t **seqnum_p, int setent)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nssuint_t off;
+ nscd_getent_context_t *ctx;
+ char *me = "nscd_map_contextp";
+
+ struct cookie_seqnum {
+ nssuint_t cookie;
+ nssuint_t seqnum;
+ } *csp;
+
+ if (buffer == NULL) {
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ off = pbuf->key_off;
+ csp = (struct cookie_seqnum *)((void *)((char *)buffer + off));
+ if (seqnum_p != NULL)
+ *seqnum_p = &csp->seqnum;
+
+ /*
+ * if called by nss_psetent, and the passed in cookie is
+ * NSCD_NEW_COOKIE, then there is no cookie yet, return
+ * a pointer pointing to where the cookie will be stored.
+ * Also because there is no cookie to validate, just
+ * return success.
+ *
+ * On the other hand, if a cookie is passed in, we need
+ * to validate the cookie before returning.
+ */
+ if (cookie_p != NULL)
+ *cookie_p = &csp->cookie;
+ if (setent == 1 && csp->cookie == NSCD_NEW_COOKIE) {
+ NSCD_RETURN_STATUS_SUCCESS(pbuf);
+ }
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "cookie = %lld, sequence number = %lld\n",
+ csp->cookie, csp->seqnum);
+
+ ctx = _nscd_is_getent_ctx(csp->cookie);
+
+ if (ctx == NULL) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid cookie (%lld)\n", csp->cookie);
+
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ if (setent == 1) {
+ /* if called by nss_psetent, reset the seq number */
+ ctx->seq_num = 1;
+ } else if (ctx->seq_num != (nscd_seq_num_t)csp->seqnum) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "invalid sequence number (%lld)\n", csp->seqnum);
+
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ contextp->ctx = (struct nss_getent_context *)ctx;
+
+ NSCD_RETURN_STATUS_SUCCESS(pbuf);
+}
+
+void
+nss_psetent(void *buffer, size_t length, pid_t pid)
+{
+ /* inputs */
+ nss_db_initf_t initf;
+ nss_getent_t context = { 0 };
+ nss_getent_t *contextp = &context;
+ nss_status_t status;
+ nssuint_t *cookiep;
+ nssuint_t *seqnump;
+ nscd_getent_context_t *ctx;
+ int rc;
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nscd_sw_return_t swret = { 0 }, *swrp = &swret;
+ char *me = "nss_psetent";
+
+ if (buffer == NULL || length == 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ /*
+ * If this is a per-user nscd, and the user does not have
+ * the necessary credential, return NSS_TRYLOCAL, so the
+ * setent/getent can be done locally in the process of the
+ * setent call
+ */
+ if (_whoami == NSCD_CHILD) {
+ OM_uint32 stat;
+
+ if (gss_inquire_cred(&stat, GSS_C_NO_CREDENTIAL,
+ NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) {
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
+ NSCD_LOG_LEVEL_DEBUG)
+ (me, "NSS_TRYLOCAL: fallback to caller process\n");
+ NSCD_RETURN_STATUS(pbuf, NSS_TRYLOCAL, 0);
+ }
+ }
+
+ status = nss_packed_context_init(buffer, length,
+ NULL, &initf, &contextp, (nss_XbyY_args_t *)NULL);
+ if (status != NSS_SUCCESS) {
+ NSCD_RETURN_STATUS(pbuf, status, -1);
+ }
+
+ /*
+ * use the generic nscd_initf for all the setent requests
+ * (the TSD key is the pointer to the packed header)
+ */
+ rc = set_initf_key(pbuf);
+ if (rc != 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL);
+ }
+ initf = nscd_initf;
+
+ /* get address of cookie and seqnum for later updates */
+ nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 1);
+ if (NSCD_STATUS_IS_NOT_OK(pbuf))
+ return;
+ /*
+ * pass the packed header buffer pointer to nss_setent
+ */
+ (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp));
+ swret.pbuf = buffer;
+
+ /* Perform local setent and set context */
+ nss_setent(NULL, initf, contextp);
+
+ /* insert cookie info into buffer and return */
+ ctx = (nscd_getent_context_t *)contextp->ctx;
+ if (ctx != NULL) {
+ *cookiep = ctx->cookie;
+ *seqnump = (nssuint_t)ctx->seq_num;
+ ctx->pid = pid;
+ } else {
+ /*
+ * not able to allocate a getent context, the
+ * client should try the enumeration locally
+ */
+ *cookiep = NSCD_LOCAL_COOKIE;
+ *seqnump = 0;
+ }
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "cookie = %lld, sequence number = %lld\n",
+ *cookiep, *seqnump);
+
+ if (ctx != NULL) {
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "cookie = %lld, sequence number = %lld\n",
+ ctx->cookie, ctx->seq_num);
+ }
+
+ /* clear the TSD key used by the generic initf */
+ clear_initf_key();
+
+ if (*cookiep == NSCD_LOCAL_COOKIE) {
+ NSCD_RETURN_STATUS(pbuf, NSS_TRYLOCAL, 0);
+ } else {
+ NSCD_RETURN_STATUS(pbuf, NSS_SUCCESS, 0);
+ }
+}
+
+void
+nss_pgetent(void *buffer, size_t length)
+{
+ /* inputs */
+ nss_db_initf_t initf;
+ nss_getent_t context;
+ nss_getent_t *contextp = &context;
+ nss_XbyY_args_t arg;
+ nss_status_t status;
+ nssuint_t *cookiep;
+ nssuint_t *seqnump;
+ nscd_getent_context_t *ctx;
+ int rc;
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ char *me = "nss_pgetent";
+
+ if (buffer == NULL || length == 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ status = nss_packed_context_init(buffer, length,
+ NULL, &initf, &contextp, &arg);
+ if (status != NSS_SUCCESS) {
+ NSCD_RETURN_STATUS(pbuf, status, -1);
+ }
+
+ /*
+ * use the generic nscd_initf for all the getent requests
+ * (the TSD key is the pointer to the packed header)
+ */
+ rc = set_initf_key(pbuf);
+ if (rc != 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL);
+ }
+ initf = nscd_initf;
+
+
+ /* verify the cookie passed in */
+ nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 0);
+ if (NSCD_STATUS_IS_NOT_OK(pbuf))
+ return;
+
+ /* Perform local search and pack results into return buffer */
+ status = nss_getent(NULL, initf, contextp, &arg);
+ NSCD_SET_STATUS(pbuf, status, -1);
+ nss_packed_set_status(buffer, length, status, &arg);
+
+ /* increment sequence number in the buffer and nscd context */
+ if (status == NSS_SUCCESS) {
+ ctx = (nscd_getent_context_t *)contextp->ctx;
+ ctx->seq_num++;
+ *seqnump = ctx->seq_num;
+ *cookiep = ctx->cookie;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getent OK, new sequence number = %lld, len = %lld,"
+ " data = [ %s ]\n", *seqnump,
+ pbuf->data_len, (char *)buffer + pbuf->data_off);
+ } else {
+ ctx = (nscd_getent_context_t *)contextp->ctx;
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "getent failed, status = %d, sequence number = %lld\n",
+ status, *seqnump);
+ }
+
+ /* clear the TSD key used by the generic initf */
+ clear_initf_key();
+}
+
+void
+nss_pendent(void *buffer, size_t length)
+{
+ nss_getent_t context;
+ nss_getent_t *contextp = &context;
+ nssuint_t *seqnump;
+ nssuint_t *cookiep;
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ char *me = "nss_pendent";
+
+ if (buffer == NULL || length == 0) {
+ NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT);
+ }
+
+ /* map the contextp from the cookie information */
+ nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 0);
+ if (NSCD_STATUS_IS_NOT_OK(pbuf))
+ return;
+
+ _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
+ (me, "endent, cookie = %lld, sequence number = %lld\n",
+ *cookiep, *seqnump);
+
+ /* Perform local endent and reset context */
+ nss_endent(NULL, NULL, contextp);
+ NSCD_RETURN_STATUS(pbuf, NSS_SUCCESS, 0);
+}
+
+/*ARGSUSED*/
+void
+nss_pdelete(void *buffer, size_t length)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+
+ /* unnecessary, kept for completeness */
+ NSCD_RETURN_STATUS_SUCCESS(pbuf);
+}
diff --git a/usr/src/cmd/nscd/nscd_switch.h b/usr/src/cmd/nscd/nscd_switch.h
new file mode 100644
index 0000000000..0522fb3851
--- /dev/null
+++ b/usr/src/cmd/nscd/nscd_switch.h
@@ -0,0 +1,399 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NSCD_SWITCH_H
+#define _NSCD_SWITCH_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nss_dbdefs.h>
+#include <thread.h>
+#include <libscf.h>
+#define __NSS_PRIVATE_INTERFACE
+#include "nsswitch_priv.h"
+#undef __NSS_PRIVATE_INTERFACE
+#include "nscd_db.h"
+#include "nscd_config.h"
+
+/*
+ * max. length of e.g. "passwd: files ldap"
+ */
+#define MAX_NSSWITCH_CONFIG_STRING_SZ 256
+
+/*
+ * max. length of the name of a NSS database
+ */
+#define MAX_NSSWITCH_CONFIG_DB_NAME_SZ 256
+
+/*
+ * nscd_nsw_config_t is an abstraction of the configuration
+ * for a NSS database
+ */
+typedef struct {
+ char *db_name;
+ char *nsw_cfg_str;
+ nss_db_params_t fe_params;
+ struct __nsw_switchconfig_v1 *nsw_config;
+ int max_src;
+ int *src_idx; /* ptr to array of */
+ /* src index */
+ int nobase; /* not shared */
+} nscd_nsw_config_t;
+
+/*
+ * nscd_be_info_t is an abstraction of a NSS backend
+ */
+typedef struct {
+ nss_backend_constr_t be_constr;
+ nss_backend_finder_t *finder;
+ void *finder_priv;
+} nscd_be_info_t;
+
+/*
+ * nscd_state_ctrl_t is used to control a nscd_nsw_state pool
+ */
+typedef struct {
+ int max;
+ int allocated;
+ int free;
+ int waiter;
+ struct nscd_nsw_state *first;
+} nscd_state_ctrl_t;
+
+/*
+ * nscd_nsw_state_base_t represents the nscd_nsw_state pool
+ * for a NSS database
+ */
+typedef struct nscd_nsw_state_base {
+ int dbi; /* which database? */
+ nscd_state_ctrl_t nsw_state;
+ nscd_state_ctrl_t nsw_state_thr;
+ int used_by_thr;
+ thread_t tid;
+ cond_t thr_cond;
+} nscd_nsw_state_base_t;
+
+/*
+ * nscd_nsw_state_t is an abstraction of all the data needed
+ * to do lookup of NSS database (e.g. "passwd" or "hosts")
+ */
+typedef struct nscd_nsw_state {
+ int dbi; /* which database? */
+ int max_src; /* is == config->num_lookups */
+ int getent; /* used by getent */
+ nss_db_params_t p;
+ struct __nsw_switchconfig_v1 *config;
+ nscd_nsw_config_t **nsw_cfg_p;
+ nscd_nsw_state_base_t *base;
+ nss_backend_t **be; /* array of backends */
+ nscd_db_t ***be_db_pp;
+ struct nscd_nsw_state *next;
+} nscd_nsw_state_t;
+
+/*
+ * nscd_getent_ctx_base_t represents the nscd_getent_ctx_base_t pool
+ * for a NSS database
+ */
+typedef struct nscd_getent_ctx_base {
+ int dbi; /* which database? */
+ int deattached; /* not associated with */
+ /* current config */
+ int max_getent_ctx;
+ int num_getent_ctx;
+ int num_waiter;
+ struct nscd_getent_context *first;
+} nscd_getent_ctx_base_t;
+
+/*
+ * nscd_getent_context_t is an abstraction of all the data needed
+ * to enumerate a NSS database (e.g. "passwd" or "hosts")
+ */
+typedef struct nscd_getent_context {
+ int dbi;
+ nscd_seq_num_t seq_num;
+ nscd_cookie_t cookie;
+ pid_t pid; /* door client's pid */
+ int n_src; /* >=max_src: end of sequence */
+ nscd_nsw_state_t *nsw_state;
+ nss_backend_t *be;
+ nscd_getent_ctx_base_t *base;
+ struct nscd_getent_context *next;
+} nscd_getent_context_t;
+
+/*
+ * nscd_smf_state_t is used to keep track of the state of the smf
+ * service associated with a NSS source (e.g. "passwd" or "hosts")
+ */
+typedef struct {
+ char *src_name;
+ int src_state;
+} nscd_smf_state_t;
+
+/*
+ * nscd_smf_state_t is used to keep track of the state of the smf
+ * service associated with a NSS source (e.g. "passwd" or "hosts")
+ */
+typedef struct {
+ int dbi; /* database index */
+ /*
+ * index of the database of which the switch policy
+ * should be used
+ */
+ int cfgdbi;
+ /*
+ * index of the pseudo database that the NSS backend
+ * does search on
+ */
+ int compati;
+ /*
+ * ptr to ptr to the siwtch config structure
+ */
+ nscd_nsw_config_t **nswcfg;
+ /*
+ * frontend params passed to nss_search or nss_*ent
+ */
+ struct nss_db_params p;
+ /*
+ * set to 1 if database is "hosts", else 2 if "ipnodes"
+ */
+ int8_t dnsi;
+ /*
+ * set to 1 if require privilege to look up the database
+ */
+ uint8_t privdb;
+} nscd_nsw_params_t;
+
+/*
+ * additional info returned by the switch engine
+ */
+typedef struct {
+ void *pbuf; /* ptr to packed buffer */
+ size_t pbufsiz; /* length of the packed buffer */
+ int srci; /* last source searched */
+ int errnum; /* errno from the backend */
+ int noarg; /* if set, backend does not use the arg structure */
+ int fallback; /* if set, may need to fall back to main nscd */
+} nscd_sw_return_t;
+
+/*
+ * static tables or global data defined in other files
+ */
+extern int _nscd_cfg_num_nsw_src;
+extern int _nscd_cfg_num_nsw_src_all;
+extern int _nscd_cfg_num_nsw_db;
+extern int _nscd_cfg_num_nsw_db_all;
+extern int _nscd_cfg_num_smf_services;
+extern nscd_cfg_id_t _nscd_cfg_nsw_src[];
+extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
+extern nscd_cfg_id_t _nscd_cfg_nsw_db[];
+extern nss_db_initf_t nscd_nss_db_initf[];
+extern nscd_cfg_id_t _nscd_cfg_smf_services[];
+extern nscd_smf_state_t *nscd_smf_service_state;
+extern nscd_db_t ***nscd_src_backend_db;
+extern nscd_nsw_config_t ***nscd_nsw_config;
+extern nscd_nsw_state_base_t **nscd_nsw_state_base;
+extern nscd_getent_ctx_base_t **nscd_getent_ctx_base;
+extern nscd_cfg_global_switch_t nscd_switch_cfg_g;
+extern nscd_cfg_switch_t *nscd_switch_cfg;
+extern nscd_cfg_stat_global_switch_t nscd_switch_stats_g;
+extern nscd_cfg_stat_switch_t *nscd_switch_stats;
+
+#define NSCD_NUM_SRC _nscd_cfg_num_nsw_src_all
+#define NSCD_NUM_DB _nscd_cfg_num_nsw_db_all
+#define NSCD_NUM_SMF_FMRI _nscd_cfg_num_smf_services
+#define NSCD_NSW_SRC_NAME(i) (_nscd_cfg_nsw_src_all + i)->name
+#define NSCD_NSW_DB_NAME(i) _nscd_cfg_nsw_db[i].name
+#define NSCD_SMF_SVC_FMRI(i) _nscd_cfg_smf_services[i].name
+#define NSCD_SMF_SVC_INDEX(i) _nscd_cfg_smf_services[i].index
+#define NSCD_SMF_SVC_STATE(i) nscd_smf_service_state[i].src_state
+#define NSCD_SW_CFG_G nscd_switch_cfg_g
+#define NSCD_SW_CFG(i) nscd_switch_cfg[i]
+#define NSCD_SW_STATS_G nscd_switch_stats_g
+#define NSCD_SW_STATS(i) nscd_switch_stats[i]
+
+/*
+ * special service states used by the switch engine
+ */
+#define NSCD_SVC_STATE_UNINITED -1
+#define NSCD_SVC_STATE_UNKNOWN_SRC -2
+
+/*
+ * prototypes
+ */
+
+void
+_nscd_put_nsw_state(
+ nscd_nsw_state_t *s);
+
+void
+_nscd_put_nsw_state_thread(
+ nscd_nsw_state_t *s);
+
+nscd_rc_t
+_nscd_get_nsw_state(
+ nss_db_root_t *rootp,
+ nscd_nsw_params_t *params);
+
+nscd_rc_t
+_nscd_get_nsw_state_thread(
+ nss_db_root_t *rootp,
+ nscd_nsw_params_t *params);
+
+nscd_rc_t
+_nscd_init_all_nsw_state_base();
+
+nscd_rc_t
+_nscd_init_nsw_state_base(
+ int dbi,
+ int lock);
+
+nscd_rc_t
+_nscd_init_all_getent_ctx();
+
+nscd_rc_t
+_nscd_init_getent_ctx_base(
+ int dbi,
+ int lock);
+
+nscd_db_t
+*_nscd_create_getent_ctxaddrDB();
+
+nscd_rc_t
+_nscd_get_getent_ctx(
+ nss_getent_t *contextpp,
+ nscd_nsw_params_t *params);
+
+void
+_nscd_put_getent_ctx(
+ nscd_getent_context_t *ctx);
+
+nscd_rc_t
+_nscd_init_all_nsw_config();
+
+nscd_rc_t
+_nscd_init_all_nsw_be_info_db();
+
+#ifdef NSCD_NSSWITCH_CONF_FROM_SMF_PROP
+nscd_rc_t
+_nscd_get_new_nsw_config(
+ scf_handle_t *hndl,
+ const char *fmri,
+ scf_propertygroup_t *pg);
+#endif
+
+nscd_rc_t
+_nscd_get_new_service_state(
+ int index,
+ scf_handle_t *hndl,
+ scf_property_t *prop);
+
+nscd_getent_context_t *
+_nscd_is_getent_ctx(
+ nscd_cookie_t cookie);
+
+nscd_rc_t
+_nscd_create_sw_struct(
+ int dbi,
+ const char *dbn,
+ const char *cfgstr,
+ void *swcfgv1,
+ nscd_nsw_params_t *params);
+
+nscd_rc_t
+_nscd_create_new_config(
+ nscd_nsw_params_t *params);
+
+void
+_nscd_free_nsw_config(
+ nscd_nsw_config_t *nswcfg);
+
+nscd_rc_t
+_nscd_init_smf_monitor();
+
+nscd_rc_t
+_nscd_alloc_nsw_config();
+
+nscd_rc_t
+_nscd_alloc_service_state_table();
+
+nscd_rc_t
+_nscd_alloc_nsw_state_base();
+
+nscd_rc_t
+_nscd_alloc_nsw_be_info_db();
+
+nscd_rc_t
+_nscd_alloc_getent_ctx_base();
+
+void
+_nscd_free_all_nsw_state_base();
+
+void
+_nscd_free_all_getent_ctx_base();
+
+void
+_nscd_free_all_nsw_config();
+
+void
+_nscd_free_all_nsw_backend_info_db();
+
+struct __nsw_switchconfig_v1 *
+_nsw_getoneconfig_v1(
+ const char *name,
+ char *linep,
+ enum __nsw_parse_err *errp);
+int
+__nsw_freeconfig_v1(
+ struct __nsw_switchconfig_v1 *conf);
+
+int
+_nscd_get_smf_state(int srci, int dbi, int recheck);
+
+void
+nss_psearch(void *buffer, size_t length);
+void
+nss_psetent(void *buffer, size_t length, pid_t pid);
+void
+nss_pgetent(void *buffer, size_t length);
+void
+nss_pendent(void *buffer, size_t length);
+void
+nss_pdelete(void *buffer, size_t length);
+
+nscd_rc_t _nscd_alloc_switch_cfg();
+nscd_rc_t _nscd_alloc_switch_stats();
+nscd_db_t *_nscd_create_getent_ctx_addrDB();
+nscd_rc_t _nscd_populate_nsw_backend_info();
+nscd_db_t *_nscd_create_getent_ctxDB();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NSCD_SWITCH_H */
diff --git a/usr/src/cmd/nscd/nscd_wait.c b/usr/src/cmd/nscd/nscd_wait.c
index b5af46749e..e091f8764c 100644
--- a/usr/src/cmd/nscd/nscd_wait.c
+++ b/usr/src/cmd/nscd/nscd_wait.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,123 +29,42 @@
* routines to wait and wake up a client waiting on a list for a
* name service request
*/
-#include <thread.h>
-#include <synch.h>
-#include "getxby_door.h"
+#include "cache.h"
int
-nscd_wait(waiter_t * wchan, mutex_t * lock, char ** key)
+nscd_wait(waiter_t *wchan, mutex_t *lock, uint8_t *key)
{
waiter_t mywait;
- cond_init(&(mywait.w_waitcv), USYNC_THREAD, 0);
+ (void) cond_init(&(mywait.w_waitcv), USYNC_THREAD, 0);
mywait.w_key = key;
mywait.w_next = wchan->w_next;
mywait.w_prev = wchan;
- if(mywait.w_next)
+ if (mywait.w_next)
mywait.w_next->w_prev = &mywait;
wchan->w_next = &mywait;
-
- while( *key == (char *) -1)
- cond_wait(&(mywait.w_waitcv), lock);
- if(mywait.w_prev)
+
+ while (*key & ST_PENDING)
+ (void) cond_wait(&(mywait.w_waitcv), lock);
+ if (mywait.w_prev)
mywait.w_prev->w_next = mywait.w_next;
- if(mywait.w_next)
+ if (mywait.w_next)
mywait.w_next->w_prev = mywait.w_prev;
- return(0);
+ return (0);
}
int
-nscd_signal(waiter_t * wchan, char ** key)
+nscd_signal(waiter_t *wchan, uint8_t *key)
{
int c = 0;
- waiter_t * tmp = wchan->w_next;
+ waiter_t *tmp = wchan->w_next;
- while(tmp) {
- if(tmp->w_key == key) {
- cond_signal(&(tmp->w_waitcv));
+ while (tmp) {
+ if (tmp->w_key == key) {
+ (void) cond_signal(&(tmp->w_waitcv));
c++;
}
tmp = tmp->w_next;
}
- return(c);
+ return (c);
}
-
-#ifdef TESTPROG
-
-static waiter_t w;
-static mutex_t l;
-static char ** blocks;
-
-static int num_threads;
-
-main(int argc, char * argv[])
-{
- int i;
- void * go();
- if(argc != 2) {
- printf("usage: %s numthreads\n", argv[0]);
- exit(1);
- }
-
- num_threads = atoi(argv[1]);
-
- blocks = (char **) malloc(sizeof(char **) * num_threads);
-
- memset(blocks, -1, sizeof(char**) * num_threads);
-
- mutex_lock(&l);
-
- for(i=0;i<num_threads;i++)
- if(thr_create(NULL, NULL, go, (void*)i, THR_NEW_LWP, NULL) != 0) {
- printf("thread_create failed\n");
- exit(2);
- }
-
-
-
- mutex_unlock(&l);
-
- sleep(5);
-
- printf("going\n");
- mutex_lock(&l);
-
- memset(blocks, 0, sizeof(char**) * num_threads);
-
- for(i=0;i<num_threads;i++)
- nscd_signal(&w, blocks+i);
-
- mutex_unlock(&l);
-
- while(num_threads--) {
- if(thr_join(NULL, NULL, NULL) < 0) {
- printf("error in join\n");
- exit(2);
- }
- }
-
- printf("all done\n");
- exit(0);
-}
-
-void * go(int index)
-{
- printf("thread %d locking\n", index);
-
- mutex_lock(&l);
-
- printf("thread %d waiting\n", index);
-
- nscd_wait(&w,&l, blocks+index);
-
- printf("thread %d unlocking\n", index);
-
- mutex_unlock(&l);
-
- thr_exit(NULL);
-}
-
-
-#endif /* TESTPROG */
-
diff --git a/usr/src/cmd/nscd/req.flg b/usr/src/cmd/nscd/req.flg
new file mode 100644
index 0000000000..e366b376b3
--- /dev/null
+++ b/usr/src/cmd/nscd/req.flg
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+echo_file usr/src/lib/libc/port/gen/getxby_door.h
+echo_file usr/src/lib/libc/inc/nsswitch_priv.h
+echo_file usr/src/lib/libsldap/common/ns_sldap.h
diff --git a/usr/src/cmd/nscd/server.c b/usr/src/cmd/nscd/server.c
index d4cba76b85..699579fdfe 100644
--- a/usr/src/cmd/nscd/server.c
+++ b/usr/src/cmd/nscd/server.c
@@ -30,139 +30,44 @@
*/
#include <stdio.h>
-#include <signal.h>
-#include <sys/door.h>
-#include <sys/types.h>
-#include <time.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/zone.h>
#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
#include <errno.h>
-#include <pthread.h>
-#include <thread.h>
#include <stdarg.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <unistd.h>
-#include <memory.h>
-#include <sys/socket.h>
-#include <net/route.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <door.h>
-#include "getxby_door.h"
-#include "server_door.h"
-#include "nscd.h"
-/* Includes for filenames of databases */
-#include <shadow.h>
-#include <userdefs.h>
-#include <netdb.h>
-#include <nss_dbdefs.h>
-#include <exec_attr.h>
-#include <prof_attr.h>
-#include <user_attr.h>
-#include <ucred.h>
-#include <priv.h>
-#include <libscf.h>
+#include <locale.h>
#include <tsol/label.h>
#include <zone.h>
-
-#define TSOL_NAME_SERVICE_DOOR "/var/tsol/doors/name_service_door"
+#include "cache.h"
+#include "nscd_log.h"
+#include "nscd_selfcred.h"
+#include "nscd_frontend.h"
+#include "nscd_common.h"
+#include "nscd_admin.h"
+#include "nscd_door.h"
+#include "nscd_switch.h"
extern int optind;
extern int opterr;
extern int optopt;
extern char *optarg;
-static void switcher(void *, char *, size_t, door_desc_t *, uint_t);
-static void rts_mon(void);
-static void usage(char *);
-static int nsc_calllen(nsc_call_t *);
-static int client_getadmin(admin_t *);
-static void getadmin(nsc_return_t *, int, nsc_call_t *);
-static int setadmin(nsc_return_t *, int, nsc_call_t *);
-static void client_killserver(void);
-static int client_setadmin(admin_t *);
-static void client_showstats(admin_t *);
-static void detachfromtty(void);
-
+#define NSCDOPT "S:Kf:c:ge:p:n:i:l:d:s:h:o:GFR"
-admin_t current_admin;
-static int will_become_server;
-
-void
-nsc_reaper(char *tbl_name, hash_t *tbl, nsc_stat_t *admin_ptr,
- mutex_t *hash_lock)
-{
- uint_t count;
- uint_t interval;
+/* assume this is a single nscd or, if multiple, the main nscd */
+int _whoami = NSCD_MAIN;
+int _doorfd = -1;
+extern int _logfd;
+static char *cfgfile = NULL;
- while (1) {
+extern nsc_ctx_t *cache_ctx_p[];
- if (current_admin.debug_level >= DBG_ALL) {
- logit("reaper_%s: %d entries in cache\n",
- tbl_name, admin_ptr->nsc_entries);
- }
- if (admin_ptr->nsc_entries > 0) {
- count = reap_hash(tbl, admin_ptr, hash_lock,
- admin_ptr->nsc_pos_ttl);
- if (current_admin.debug_level >= DBG_ALL) {
- logit("reaper_%s: reaped %d entries\n",
- tbl_name, count);
- }
- } else {
- /*
- * We set a minimum wait of 60 before checking again;
- * we don't want to sleep for no time at all.
- * We don't clamp it for the reaping itself, that is
- * done in reap_hash, and with a different minimum.
- */
- interval = admin_ptr->nsc_pos_ttl;
- if (interval < 60) interval = 60;
- if (current_admin.debug_level >= DBG_ALL) {
- logit(
- "reaper_%s: Nothing to reap, sleep %d\n",
- tbl_name, interval);
- }
- sleep(interval);
- }
- }
-}
-
-nsc_stat_t *
-getcacheptr(char *s)
-{
- static const char *caches[7] = {"passwd", "group", "hosts", "ipnodes",
- "exec_attr", "prof_attr", "user_attr" };
-
- if (strncmp(caches[0], s, strlen(caches[0])) == 0)
- return (&current_admin.passwd);
-
- if (strncmp(caches[1], s, strlen(caches[1])) == 0)
- return (&current_admin.group);
-
- if (strncmp(caches[2], s, strlen(caches[2])) == 0)
- return (&current_admin.host);
-
- if (strncmp(caches[3], s, strlen(caches[3])) == 0)
- return (&current_admin.node);
-
- if (strncmp(caches[4], s, strlen(caches[4])) == 0)
- return (&current_admin.exec);
-
- if (strncmp(caches[5], s, strlen(caches[5])) == 0)
- return (&current_admin.prof);
-
- if (strncmp(caches[6], s, strlen(caches[6])) == 0)
- return (&current_admin.user);
+static void usage(char *);
+static void detachfromtty(void);
- return (NULL);
-}
+static int debug_level = 0;
+static char logfile[128] = { 0 };
+static int will_become_server;
static char *
getcacheopt(char *s)
@@ -173,37 +78,6 @@ getcacheopt(char *s)
}
/*
- * routine to check if server is already running
- */
-
-static int
-nsc_ping(void)
-{
- nsc_data_t data;
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- data.nsc_call.nsc_callnumber = NULLCALL;
- ndata = sizeof (data);
- adata = sizeof (data);
- dptr = &data;
- return (_nsc_trydoorcall(&dptr, &ndata, &adata));
-}
-
-static void
-dozip(void)
-{
- /* not much here */
-}
-
-static void
-keep_open_dns_socket(void)
-{
- _res.options |= RES_STAYOPEN; /* just keep this udp socket open */
-}
-
-/*
* declaring this causes the files backend to use hashing
* this is of course an utter hack, but provides a nice
* quiet back door to enable this feature for only the nscd.
@@ -211,242 +85,11 @@ keep_open_dns_socket(void)
void
__nss_use_files_hash(void)
{
-
}
-/*
- *
- * The allocation of resources for cache lookups is an interesting
- * problem, and one that has caused several bugs in the beta release
- * of 2.5. In particular, the introduction of a thottle to prevent
- * the creation of excessive numbers of LWPs in the case of a failed
- * name service has led to a denial of service problem when the
- * name service request rate exceeds the name service's ability
- * to respond. As a result, I'm implementing the following
- * algorithm:
- *
- * 1) We cap the number of total threads.
- * 2) We save CACHE_THREADS of those for cache lookups only.
- * 3) We use a common pool of 2/3 of the remain threads that are used first
- * 4) We save the remainder and allocate 1/3 of it for table specific lookups
- *
- * The intent is to prevent the failure of a single name service from
- * causing denial of service, and to always have threads available for
- * cached lookups. If a request comes in and the answer isn't in the
- * cache and we cannot get a thread, we simply return NOSERVER, forcing
- * the client to lookup the
- * data itself. This will prevent the types of starvation seen
- * at UNC due to a single threaded DNS backend, and allows the cache
- * to eventually become filled.
- *
- */
-/* 7 tables: passwd, group, hosts, ipnodes, exec_attr, prof_attr, user_attr */
-#define NSCD_TABLES 7
-#define TABLE_THREADS 10
-#define COMMON_THREADS 20
-#define CACHE_MISS_THREADS (COMMON_THREADS + NSCD_TABLES * TABLE_THREADS)
-#define CACHE_HIT_THREADS 20
-#define MAX_SERVER_THREADS (CACHE_HIT_THREADS + CACHE_MISS_THREADS)
-
-static sema_t common_sema;
-static sema_t passwd_sema;
-static sema_t hosts_sema;
-static sema_t nodes_sema;
-static sema_t group_sema;
-static sema_t exec_sema;
-static sema_t prof_sema;
-static sema_t user_sema;
-static thread_key_t lookup_state_key;
-
-static void
-initialize_lookup_clearance(void)
-{
- thr_keycreate(&lookup_state_key, NULL);
- (void) sema_init(&common_sema, COMMON_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&passwd_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&hosts_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&nodes_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&group_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&exec_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&prof_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&user_sema, TABLE_THREADS, USYNC_THREAD, 0);
-}
-
-int
-get_clearance(int callnumber)
-{
- sema_t *table_sema = NULL;
- char *tab;
-
- if (sema_trywait(&common_sema) == 0) {
- thr_setspecific(lookup_state_key, NULL);
- return (0);
- }
-
- switch (MASKUPDATEBIT(callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- tab = "passwd";
- table_sema = &passwd_sema;
- break;
-
- case GETGRNAM:
- case GETGRGID:
- tab = "group";
- table_sema = &group_sema;
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- tab = "hosts";
- table_sema = &hosts_sema;
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- tab = "ipnodes";
- table_sema = &nodes_sema;
- break;
- case GETEXECID:
- tab = "exec_attr";
- table_sema = &exec_sema;
- break;
-
- case GETPROFNAM:
- tab = "prof_attr";
- table_sema = &prof_sema;
- break;
-
- case GETUSERNAM:
- tab = "user_attr";
- table_sema = &user_sema;
- break;
-
- }
-
- if (sema_trywait(table_sema) == 0) {
- thr_setspecific(lookup_state_key, (void*)1);
- return (0);
- }
-
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- logit("get_clearance: throttling load for %s table\n", tab);
- }
- return (-1);
-}
-
-int
-release_clearance(int callnumber)
-{
- int which;
-
- sema_t *table_sema = NULL;
-
- thr_getspecific(lookup_state_key, (void**)&which);
-
- if (which == 0) /* from common pool */ {
- (void) sema_post(&common_sema);
- return (0);
- }
-
- switch (MASKUPDATEBIT(callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- table_sema = &passwd_sema;
- break;
-
- case GETGRNAM:
- case GETGRGID:
- table_sema = &group_sema;
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- table_sema = &hosts_sema;
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- table_sema = &nodes_sema;
- break;
-
- case GETEXECID:
- table_sema = &exec_sema;
- break;
-
- case GETPROFNAM:
- table_sema = &prof_sema;
- break;
-
- case GETUSERNAM:
- table_sema = &user_sema;
- break;
- }
-
- (void) sema_post(table_sema);
- return (0);
-}
-
-
-static mutex_t create_lock;
-static int nscd_max_servers = MAX_SERVER_THREADS;
-static int num_servers = 0;
-static thread_key_t server_key;
-
-/*
- * Bind a TSD value to a server thread. This enables the destructor to
- * be called if/when this thread exits. This would be a programming error,
- * but better safe than sorry.
- */
-/*ARGSUSED*/
-static void *
-server_tsd_bind(void *arg)
-{
- static void *value = 0;
-
- /* disable cancellation to avoid hangs if server threads disappear */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- thr_setspecific(server_key, value);
- door_return(NULL, 0, NULL, 0);
-
- /* make lint happy */
- return (NULL);
-}
-
-/*
- * Server threads are created here.
- */
-/*ARGSUSED*/
-static void
-server_create(door_info_t *dip)
-{
- (void) mutex_lock(&create_lock);
- if (++num_servers > nscd_max_servers) {
- num_servers--;
- (void) mutex_unlock(&create_lock);
- return;
- }
- (void) mutex_unlock(&create_lock);
- thr_create(NULL, 0, server_tsd_bind, NULL, THR_BOUND|THR_DETACHED,
- NULL);
-}
-
-/*
- * Server thread are destroyed here
- */
-/*ARGSUSED*/
-static void
-server_destroy(void *arg)
-{
- (void) mutex_lock(&create_lock);
- num_servers--;
- (void) mutex_unlock(&create_lock);
-}
-
-static char **saved_argv;
-static char saved_execname[MAXPATHLEN];
+static int saved_argc = 0;
+static char **saved_argv = NULL;
+static char saved_execname[MAXPATHLEN];
static void
save_execname()
@@ -457,23 +100,31 @@ save_execname()
if (name[0] != '/') { /* started w/ relative path */
(void) getcwd(saved_execname, MAXPATHLEN);
- strlcat(saved_execname, "/", MAXPATHLEN);
+ (void) strlcat(saved_execname, "/", MAXPATHLEN);
}
- strlcat(saved_execname, name, MAXPATHLEN);
+ (void) strlcat(saved_execname, name, MAXPATHLEN);
}
int
main(int argc, char ** argv)
{
- int did;
- int opt;
- int errflg = 0;
- int showstats = 0;
- int doset = 0;
- int loaded_config_file = 0;
- struct stat buf;
- sigset_t myset;
- struct sigaction action;
+ int opt;
+ int errflg = 0;
+ int showstats = 0;
+ int doset = 0;
+ nscd_rc_t rc;
+ char *me = "main()";
+ char *ret_locale;
+ char *ret_textdomain;
+ char msg[128];
+
+ ret_locale = setlocale(LC_ALL, "");
+ if (ret_locale == NULL)
+ (void) fprintf(stderr, gettext("Unable to set locale\n"));
+
+ ret_textdomain = textdomain(TEXT_DOMAIN);
+ if (ret_textdomain == NULL)
+ (void) fprintf(stderr, gettext("Unable to set textdomain\n"));
/*
* The admin model for TX is that labeled zones are managed
@@ -482,250 +133,207 @@ main(int argc, char ** argv)
*/
if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID)) {
(void) fprintf(stderr,
- "With Trusted Extensions nscd runs only in " \
- "the global zone.\n");
+gettext("With Trusted Extensions nscd runs only in the global zone.\n"));
exit(1);
}
/*
- * Special case non-root user here - he can just print stats
+ * Special case non-root user here - he can just print stats
*/
-
if (geteuid()) {
- if (argc != 2 || strcmp(argv[1], "-g")) {
+ if (argc != 2 ||
+ (strcmp(argv[1], "-g") && strcmp(argv[1], "-G"))) {
(void) fprintf(stderr,
- "Must be root to use any option other than "\
- "-g.\n\n");
+ gettext("Must be root to use any option other than -g\n\n"));
usage(argv[0]);
}
- if ((nsc_ping() != SUCCESS) ||
- (client_getadmin(&current_admin) != 0)) {
+ if (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS) {
(void) fprintf(stderr,
- "%s doesn't appear to be running.\n", argv[0]);
+ gettext("%s doesn't appear to be running.\n"),
+ argv[0]);
exit(1);
}
- client_showstats(&current_admin);
+ if (_nscd_client_getadmin(argv[1][1]) != 0) {
+ (void) fprintf(stderr,
+ gettext("unable to get configuration and statistics data\n"));
+ exit(1);
+ }
+
+ _nscd_client_showstats();
exit(0);
}
-
-
/*
- * Determine if there is already a daemon running
+ * Determine if there is already a daemon (main nscd) running.
+ * If not, will start it. Forker NSCD will always become a
+ * daemon.
*/
+ will_become_server = (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS);
+ if (argc >= 2 && strcmp(argv[1], "-F") == 0) {
+ will_become_server = 1;
+ _whoami = NSCD_FORKER;
- will_become_server = (nsc_ping() != SUCCESS);
-
- /*
- * process usual options
- */
+ /*
+ * allow time for the main nscd to get ready
+ * to receive the IMHERE door request this
+ * process will send later
+ */
+ (void) usleep(100000);
+ }
/*
- * load normal config file
+ * first get the config file path. Also detect
+ * invalid option as soon as possible.
*/
+ while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) {
+ switch (opt) {
- if (will_become_server) {
- static const nsc_stat_t defaults = {
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 211, /* suggested size */
- 1, /* enabled */
- 0, /* invalidate cmd */
- 600, /* positive ttl */
- 10, /* netative ttl */
- 20, /* keep hot */
- 0, /* old data not ok */
- 1 }; /* check files */
-
- current_admin.passwd = defaults;
- current_admin.group = defaults;
- current_admin.host = defaults;
- current_admin.node = defaults;
- current_admin.exec = defaults;
- current_admin.prof = defaults;
- current_admin.user = defaults;
-
- current_admin.logfile[0] = '\0';
-
- if (access("/etc/nscd.conf", R_OK) == 0) {
- if (nscd_parse(argv[0], "/etc/nscd.conf") < 0) {
+ case 'f':
+ if ((cfgfile = strdup(optarg)) == NULL)
exit(1);
+ break;
+ case 'g':
+ if (will_become_server) {
+ (void) fprintf(stderr,
+ gettext("nscd not running, no statistics to show\n\n"));
+ errflg++;
+ }
+ break;
+ case 'i':
+ if (will_become_server) {
+ (void) fprintf(stderr,
+ gettext("nscd not running, no cache to invalidate\n\n"));
+ errflg++;
}
- loaded_config_file++;
+ break;
+
+ case '?':
+ errflg++;
+ break;
}
+
}
+ if (errflg)
+ usage(argv[0]);
+
+ /*
+ * perform more initialization and load configuration
+ * if to become server
+ */
+ if (will_become_server) {
- else {
- if (client_getadmin(&current_admin)) {
+ /* initialize switch engine and config/stats management */
+ if ((rc = _nscd_init(cfgfile)) != NSCD_SUCCESS) {
(void) fprintf(stderr,
- "Cannot contact nscd properly(?)\n");
+ gettext("initialization of switch failed (rc = %d)\n"), rc);
exit(1);
}
- current_admin.logfile[0] = '\0';
+ /*
+ * initialize cache store
+ */
+ if ((rc = init_cache(0)) != NSCD_SUCCESS) {
+ (void) fprintf(stderr,
+ gettext("initialization of cache store failed (rc = %d)\n"), rc);
+ exit(1);
+ }
}
- while ((opt = getopt(argc, argv,
- "S:Kf:c:ge:p:n:i:l:d:s:h:o:")) != EOF) {
- nsc_stat_t *cache;
- char *cacheopt;
+ /*
+ * process usual options
+ */
+ optind = 1; /* this is a rescan */
+ *msg = '\0';
+ while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) {
switch (opt) {
- case 'S': /* undocumented feature */
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_secure_mode = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_secure_mode = 0;
- else
- errflg++;
- break;
-
case 'K': /* undocumented feature */
- client_killserver();
+ (void) _nscd_doorcall(NSCD_KILLSERVER);
exit(0);
break;
- case 'f':
- doset++;
- loaded_config_file++;
- if (nscd_parse(argv[0], optarg) < 0) {
- exit(1);
- }
- break;
-
+ case 'G':
case 'g':
showstats++;
break;
case 'p':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'p',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_pos_ttl = atoi(cacheopt);
break;
case 'n':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'n',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_neg_ttl = atoi(cacheopt);
break;
case 'c':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'c',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
-
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_check_files = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_check_files = 0;
- else
- errflg++;
break;
-
case 'i':
doset++;
- cache = getcacheptr(optarg);
- if (!cache) {
+ if (_nscd_add_admin_mod(optarg, 'i', NULL,
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_invalidate = 1;
break;
case 'l':
doset++;
- (void) strlcpy(current_admin.logfile, optarg, 128);
+ (void) strlcpy(logfile, optarg, 128);
+ (void) _nscd_add_admin_mod(NULL, 'l', optarg,
+ msg, sizeof (msg));
break;
case 'd':
-
doset++;
- current_admin.debug_level = atoi(optarg);
+ debug_level = atoi(optarg);
+ (void) _nscd_add_admin_mod(NULL, 'd', optarg,
+ msg, sizeof (msg));
break;
- case 's':
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
+ case 'S':
+ /* silently ignore secure-mode */
+ break;
- cache->nsc_suggestedsize = atoi(cacheopt);
+ case 's':
+ /* silently ignore suggested-size */
+ break;
+ case 'o':
+ /* silently ignore old-data-ok */
break;
case 'h':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'h',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_keephot = atoi(cacheopt);
break;
- case 'o':
+ case 'e':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'e',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_old_data_ok = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_old_data_ok = 0;
- else
- errflg++;
break;
- case 'e':
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_enabled = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_enabled = 0;
- else
- errflg++;
+ case 'F':
+ _whoami = NSCD_FORKER;
break;
default:
@@ -735,548 +343,123 @@ main(int argc, char ** argv)
}
- if (errflg)
+ if (errflg) {
+ if (*msg != '\0')
+ (void) fprintf(stderr, "\n%s: %s\n\n", argv[0], msg);
usage(argv[0]);
-
- if (!will_become_server) {
-
- if (showstats) {
- client_showstats(&current_admin);
- }
-
- if (doset) {
- if (client_setadmin(&current_admin) < 0) {
- (void) fprintf(stderr,
- "Error during admin call\n");
- exit(1);
- }
- }
- if (!showstats && !doset) {
- (void) fprintf(stderr,
- "%s already running.... no admin specified\n",
- argv[0]);
- }
- exit(0);
}
/*
- * daemon from here ou
+ * if main nscd already running and not forker nscd,
+ * can only do admin work
*/
+ if (_whoami == NSCD_MAIN) {
+ if (!will_become_server) {
+ if (showstats) {
+ if (_nscd_client_getadmin('g')) {
+ (void) fprintf(stderr,
+ gettext("Cannot contact nscd properly(?)\n"));
+ exit(1);
+ }
+ _nscd_client_showstats();
+ }
- if (!loaded_config_file) {
- (void) fprintf(stderr,
- "No configuration file specifed and /etc/nscd.conf" \
- "not present\n");
- exit(1);
- }
-
- saved_argv = argv;
- save_execname();
-
- if (current_admin.debug_level) {
- /* we're debugging... */
- if (strlen(current_admin.logfile) == 0)
- /* no specified log file */
- (void) strcpy(current_admin.logfile, "stderr");
- else
- (void) nscd_set_lf(&current_admin,
- current_admin.logfile);
- } else {
- if (strlen(current_admin.logfile) == 0)
- (void) strcpy(current_admin.logfile, "/dev/null");
- (void) nscd_set_lf(&current_admin, current_admin.logfile);
- detachfromtty();
- }
-
- /* perform some initialization */
- initialize_lookup_clearance();
- keep_open_dns_socket();
- getpw_init();
- getgr_init();
- gethost_init();
- getnode_init();
- getexec_init();
- getprof_init();
- getuser_init();
-
- /* Establish our own server thread pool */
-
- door_server_create(server_create);
- if (thr_keycreate(&server_key, server_destroy) != 0) {
- perror("thr_keycreate");
- exit(-1);
- }
-
- /* Create a door */
-
- if ((did = door_create(switcher, NAME_SERVICE_DOOR_COOKIE,
- DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
- perror("door_create");
- exit(-1);
- }
-
- /* bind to file system */
-
- if (is_system_labeled()) {
- if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) {
- int newfd;
- if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) {
- logit("Cannot create %s:%s\n",
- TSOL_NAME_SERVICE_DOOR, strerror(errno));
- exit(1);
+ if (doset) {
+ if (_nscd_client_setadmin() < 0) {
+ (void) fprintf(stderr,
+ gettext("Error during admin call\n"));
+ exit(1);
+ }
}
- (void) close(newfd);
- }
- if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) {
- if (errno != EEXIST) {
- logit("Cannot symlink %s:%s\n",
- NAME_SERVICE_DOOR, strerror(errno));
- exit(1);
+ if (!showstats && !doset) {
+ (void) fprintf(stderr,
+gettext("%s already running.... no administration option specified\n"),
+ argv[0]);
}
+ exit(0);
}
- } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
- int newfd;
- if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) {
- logit("Cannot create %s:%s\n", NAME_SERVICE_DOOR,
- strerror(errno));
- exit(1);
- }
- (void) close(newfd);
- }
-
- if (fattach(did, NAME_SERVICE_DOOR) < 0) {
- if ((errno != EBUSY) ||
- (fdetach(NAME_SERVICE_DOOR) < 0) ||
- (fattach(did, NAME_SERVICE_DOOR) < 0)) {
- perror("door_attach");
- exit(2);
- }
- }
-
- action.sa_handler = dozip;
- action.sa_flags = 0;
- (void) sigemptyset(&action.sa_mask);
- (void) sigemptyset(&myset);
- (void) sigaddset(&myset, SIGHUP);
-
- if (sigaction(SIGHUP, &action, NULL) < 0) {
- perror("sigaction");
- exit(1);
- }
-
- if (thr_sigsetmask(SIG_BLOCK, &myset, NULL) < 0) {
- perror("thr_sigsetmask");
- exit(1);
- }
-
-
- /*
- * kick off revalidate threads
- */
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getnode_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getgr_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getexec_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getprof_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getuser_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- /*
- * kick off reaper threads
- */
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_uid_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getgr_uid_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getgr_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_addr_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getnode_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getnode_addr_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getexec_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getprof_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getuser_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
}
/*
- * kick off routing socket monitor thread
+ * daemon from here on
*/
- if (thr_create(NULL, NULL,
- (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
+ if (_whoami == NSCD_MAIN) {
- if (thr_sigsetmask(SIG_UNBLOCK, &myset, NULL) < 0) {
- perror("thr_sigsetmask");
- return (1);
- }
-
- for (;;) {
- (void) pause();
- logit("Reloading /etc/nscd.conf\n");
- nscd_parse(argv[0], "/etc/nscd.conf");
- }
-}
-
-
-/*ARGSUSED*/
-static void
-switcher(void *cookie, char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- time_t now;
-
- static time_t last_nsswitch_check;
- static time_t last_nsswitch_modified;
- static time_t last_resolv_modified;
-
- static mutex_t nsswitch_lock;
-
- nsc_call_t *ptr = (nsc_call_t *)argp;
-
- if (argp == DOOR_UNREF_DATA) {
- (void) printf("Door Slam... exiting\n");
- exit(0);
- }
-
- if (ptr == NULL) { /* empty door call */
- (void) door_return(NULL, 0, 0, 0); /* return the favor */
- }
-
- now = time(NULL);
-
- /*
- * just in case check
- */
-
- (void) mutex_lock(&nsswitch_lock);
-
- if (now - last_nsswitch_check > 10) {
- struct stat nss_buf;
- struct stat res_buf;
-
- last_nsswitch_check = now;
-
- (void) mutex_unlock(&nsswitch_lock); /* let others continue */
+ /* save enough info in case need to restart or fork */
+ saved_argc = argc;
+ saved_argv = argv;
+ save_execname();
/*
- * This code keeps us from statting resolv.conf
- * if it doesn't exist, yet prevents us from ignoring
- * it if it happens to disappear later on for a bit.
+ * if a log file is not specified, set it to
+ * "stderr" or "/dev/null" based on debug level
*/
+ if (_logfd < 0 && *logfile == '\0') {
+ if (debug_level != 0)
+ /* we're debugging... */
+ (void) strcpy(logfile, "stderr");
+ else
+ (void) strcpy(logfile, "/dev/null");
- if (last_resolv_modified >= 0) {
- if (stat("/etc/resolv.conf", &res_buf) < 0) {
- if (last_resolv_modified == 0)
- last_resolv_modified = -1;
- else
- res_buf.st_mtime = last_resolv_modified;
- } else if (last_resolv_modified == 0) {
- last_resolv_modified = res_buf.st_mtime;
- }
+ (void) _nscd_add_admin_mod(NULL, 'l', logfile,
+ msg, sizeof (msg));
}
- if (stat("/etc/nsswitch.conf", &nss_buf) < 0) {
-
- /*EMPTY*/;
-
- } else if (last_nsswitch_modified == 0) {
+ /* activate command options */
+ if (_nscd_server_setadmin(NULL) != NSCD_SUCCESS) {
+ (void) fprintf(stderr,
+ gettext("unable to set command line options\n"));
+ exit(1);
+ }
- last_nsswitch_modified = nss_buf.st_mtime;
+ if (debug_level) {
+ /* we're debugging, no forking of nscd */
- } else if ((last_nsswitch_modified < nss_buf.st_mtime) ||
- ((last_resolv_modified > 0) &&
- (last_resolv_modified < res_buf.st_mtime))) {
- static mutex_t exit_lock;
- char *fmri;
/*
- * time for restart
+ * forker nscd will be started if self credential
+ * is configured
*/
- logit("nscd restart due to /etc/nsswitch.conf or "\
- "resolv.conf change\n");
+ _nscd_start_forker(saved_execname, saved_argc,
+ saved_argv);
+ } else {
/*
- * try to restart under smf
+ * daemonize the nscd (forker nscd will also
+ * be started if self credential is configured)
*/
- if ((fmri = getenv("SMF_FMRI")) == NULL) {
- /* not running under smf - reexec */
- execv(saved_execname, saved_argv);
- exit(1); /* just in case */
- }
-
- mutex_lock(&exit_lock); /* prevent multiple restarts */
- if (smf_restart_instance(fmri) == 0)
- sleep(10); /* wait a bit */
- exit(1); /* give up waiting for resurrection */
+ detachfromtty();
}
-
- } else
- (void) mutex_unlock(&nsswitch_lock);
-
- switch (ptr->nsc_callnumber) {
-
- case NULLCALL:
- u.data.nsc_ret.nsc_return_code = SUCCESS;
- u.data.nsc_ret.nsc_bufferbytesused = sizeof (nsc_return_t);
- break;
-
-
- case GETPWNAM:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETPWUID:
- getpw_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETGRNAM:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETGRGID:
- getgr_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETHOSTBYNAME:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETHOSTBYADDR:
- gethost_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETIPNODEBYNAME:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETIPNODEBYADDR:
- getnode_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETEXECID:
- *(argp + arg_size - 1) = 0;
- getexec_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETPROFNAM:
- *(argp + arg_size - 1) = 0;
- getprof_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETUSERNAM:
- *(argp + arg_size - 1) = 0;
- getuser_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETADMIN:
- getadmin(&u.data.nsc_ret, sizeof (u), ptr);
- break;
-
- case SETADMIN:
- case KILLSERVER: {
-
- ucred_t *uc = NULL;
- const priv_set_t *eset;
- zoneid_t zoneid;
-
- if (door_ucred(&uc) != 0) {
- perror("door_ucred");
- u.data.nsc_ret.nsc_return_code = NOTFOUND;
- break;
- }
-
- eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
- zoneid = ucred_getzoneid(uc);
-
- if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) ||
- eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) :
- ucred_geteuid(uc) != 0) {
- logit("SETADMIN call failed(cred): caller pid %d, "
- "uid %d, euid %d, zoneid %d\n", ucred_getpid(uc),
- ucred_getruid(uc), ucred_geteuid(uc), zoneid);
- u.data.nsc_ret.nsc_return_code = NOTFOUND;
- ucred_free(uc);
- break;
- }
-
- if (ptr->nsc_callnumber == KILLSERVER) {
- logit("Nscd received KILLSERVER cmd from pid %d, "
- "uid %d, euid %d, zoneid %d\n", ucred_getpid(uc),
- ucred_getruid(uc), ucred_geteuid(uc), zoneid);
- exit(0);
- } else {
- if (setadmin(&u.data.nsc_ret, sizeof (u), ptr) != 0)
- logit("SETADMIN call failed\n");
- }
- ucred_free(uc);
- break;
+ } else { /* NSCD_FORKER */
+ (void) open("/dev/null", O_RDWR, 0);
+ (void) dup(0);
+ if (_logfd != 2)
+ (void) dup(0);
}
- default:
- logit("Unknown name service door call op %d\n",
- ptr->nsc_callnumber);
- u.data.nsc_ret.nsc_return_code = -1;
- u.data.nsc_ret.nsc_bufferbytesused = sizeof (nsc_return_t);
- break;
-
+ /* set up door and establish our own server thread pool */
+ if ((_doorfd = _nscd_setup_server(saved_execname, saved_argv)) == -1) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to set up door\n");
+ exit(1);
}
- door_return((char *)&u.data, u.data.nsc_ret.nsc_bufferbytesused,
- NULL, 0);
-}
-/*
- * Monitor the routing socket. Address lists stored in the ipnodes
- * cache are sorted based on destination address selection rules,
- * so when things change that could affect that sorting (interfaces
- * go up or down, flags change, etc.), we clear that cache so the
- * list will be re-ordered the next time the hostname is resolved.
- */
-static void
-rts_mon(void)
-{
- int rt_sock, rdlen;
- union {
- struct {
- struct rt_msghdr rtm;
- struct sockaddr_storage addrs[RTA_NUMBITS];
- } r;
- struct if_msghdr ifm;
- struct ifa_msghdr ifam;
- } mbuf;
- struct ifa_msghdr *ifam = &mbuf.ifam;
-
- rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
- if (rt_sock < 0) {
- logit("Failed to open routing socket: %s\n", strerror(errno));
- thr_exit(0);
+ /* inform the main nscd that this forker is ready */
+ if (_whoami == NSCD_FORKER) {
+ int ret;
+
+ for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
+ ret = _nscd_doorcall_sendfd(_doorfd,
+ NSCD_IMHERE | (NSCD_FORKER & NSCD_WHOAMI),
+ NULL, 0, NULL);
}
for (;;) {
- rdlen = read(rt_sock, &mbuf, sizeof (mbuf));
- if (rdlen <= 0) {
- if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) {
- logit("routing socket read: %s\n",
- strerror(errno));
- thr_exit(0);
- }
- continue;
- }
- if (ifam->ifam_version != RTM_VERSION) {
- logit("rx unknown version (%d) on routing socket.\n",
- ifam->ifam_version);
- continue;
- }
- switch (ifam->ifam_type) {
- case RTM_NEWADDR:
- case RTM_DELADDR:
- getnode_name_invalidate();
- break;
- case RTM_ADD:
- case RTM_DELETE:
- case RTM_CHANGE:
- case RTM_GET:
- case RTM_LOSING:
- case RTM_REDIRECT:
- case RTM_MISS:
- case RTM_LOCK:
- case RTM_OLDADD:
- case RTM_OLDDEL:
- case RTM_RESOLVE:
- case RTM_IFINFO:
- break;
- default:
- logit("rx unknown msg type (%d) on routing socket.\n",
- ifam->ifam_type);
- break;
- }
+ (void) pause();
+ (void) _nscd_doorcall(NSCD_REFRESH);
}
+
+ /* NOTREACHED */
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
}
static void
@@ -1289,609 +472,43 @@ usage(char *s)
(void) fprintf(stderr,
" [-n cachename,negative_time_to_live]\n");
(void) fprintf(stderr,
- " [-i cachename] [-s cachename,suggestedsize]\n");
-
+ " [-i cachename]\n");
(void) fprintf(stderr,
- " [-h cachename,keep_hot_count] "\
- "[-o cachename,\"yes\"|\"no\"]\n");
-
+ " [-h cachename,keep_hot_count]\n");
(void) fprintf(stderr,
" [-e cachename,\"yes\"|\"no\"] [-g] " \
"[-c cachename,\"yes\"|\"no\"]\n");
-
(void) fprintf(stderr,
" [-f configfilename] \n");
-
(void) fprintf(stderr,
- "\n Supported caches: passwd, group, hosts, ipnodes\n");
-
+ "\n Supported caches:\n");
(void) fprintf(stderr,
- " exec_attr, prof_attr, and user_attr.\n");
-
+ " audit_user, auth_attr, bootparams, ethers\n");
+ (void) fprintf(stderr,
+ " exec_attr, group, hosts, ipnodes, netmasks\n");
+ (void) fprintf(stderr,
+ " networks, passwd, printers, prof_attr, project\n");
+ (void) fprintf(stderr,
+ " protocols, rpc, services, tnrhtp, tnrhdb\n");
+ (void) fprintf(stderr,
+ " user_attr\n");
exit(1);
-
-}
-
-
-static int logfd = 2;
-
-int
-nscd_set_lf(admin_t *ptr, char *s)
-{
- int newlogfd;
-
- /*
- * we don't really want to try and open the log file
- * /dev/null since that will fail w/ our security fixes
- */
-
- if (*s == 0) {
- /* ignore empty log file specs */
- /*EMPTY*/;
- } else if (s == NULL || strcmp(s, "/dev/null") == 0) {
- (void) strcpy(current_admin.logfile, "/dev/null");
- (void) close(logfd);
- logfd = -1;
- } else {
- /*
- * In order to open this file securely, we'll try a few tricks
- */
-
- if ((newlogfd = open(s, O_EXCL|O_WRONLY|O_CREAT, 0644)) < 0) {
- /*
- * File already exists... now we need to get cute
- * since opening a file in a world-writeable directory
- * safely is hard = it could be a hard link or a
- * symbolic link to a system file.
- */
- struct stat before;
-
- if (lstat(s, &before) < 0) {
- logit("Cannot open new logfile \"%s\": %sn",
- s, strerror(errno));
- return (-1);
- }
-
- if (S_ISREG(before.st_mode) && /* no symbolic links */
- (before.st_nlink == 1) && /* no hard links */
- (before.st_uid == 0)) { /* owned by root */
- if ((newlogfd =
- open(s, O_APPEND|O_WRONLY, 0644)) < 0) {
- logit("Cannot open new "\
- "logfile \"%s\": %s\n", s,
- strerror(errno));
- return (-1);
- }
- } else {
- logit("Cannot use specified logfile \"%s\": "\
- "file is/has links or isn't owned by "\
- "root\n", s);
- return (-1);
- }
- }
-
- (void) strlcpy(ptr->logfile, s, 128);
- (void) close(logfd);
- logfd = newlogfd;
- logit("Start of new logfile %s\n", s);
- }
- return (0);
-}
-
-void
-logit(char *format, ...)
-{
- static mutex_t loglock;
- struct timeval tv;
-
-#define LOGBUFLEN 1024
- char buffer[LOGBUFLEN];
-
- va_list ap;
- va_start(ap, format);
-
- if (logfd >= 0) {
- int safechars, offset;
- if (gettimeofday(&tv, NULL) != 0 ||
- ctime_r(&tv.tv_sec, buffer, LOGBUFLEN) == NULL) {
- (void) snprintf(buffer, LOGBUFLEN,
- "<time conversion failed>\t");
- } else {
- /*
- * ctime_r() includes some stuff we don't want;
- * adjust length to overwrite " YYYY\n".
- */
- offset = strlen(buffer) - 6;
- safechars = LOGBUFLEN - (offset - 1);
- (void) snprintf(buffer + offset, safechars, ".%.4ld\t",
- tv.tv_usec/100);
- }
- offset = strlen(buffer);
- safechars = LOGBUFLEN - (offset - 1);
- if (vsnprintf(buffer + offset, safechars, format, ap) >
- safechars) {
- (void) strncat(buffer, "...\n", LOGBUFLEN);
- }
-
- (void) mutex_lock(&loglock);
- (void) write(logfd, buffer, strlen(buffer));
- (void) mutex_unlock(&loglock);
- }
-
- va_end(ap);
-#undef LOGBUFLEN
}
-static void
-do_update(nsc_call_t *in)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- time_t now = time(NULL);
-
- switch (MASKUPDATEBIT(in->nsc_callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- getpw_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETGRNAM:
- case GETGRGID:
- getgr_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- gethost_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- getnode_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETEXECID:
- getexec_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETPROFNAM:
- getprof_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETUSERNAM:
- getuser_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- default:
- assert(0);
- break;
- }
-
- free(in);
-}
-
-int
-launch_update(nsc_call_t *in)
-{
- nsc_call_t *c;
-
- int l = nsc_calllen(in);
-
- in->nsc_callnumber |= UPDATEBIT;
-
- if ((c = malloc(l)) == NULL) {
- logit("thread create failed: %s\n", strerror(errno));
- exit(1);
- }
- (void) memcpy(c, in, l);
-
- if (current_admin.debug_level >= DBG_ALL) {
- logit("launching update\n");
- }
-
- if (thr_create(NULL,
- NULL,
- (void *(*)(void*))do_update,
- c,
- 0|THR_DETACHED, NULL) != 0) {
- logit("thread create failed\n");
- exit(1);
- }
-
- return (0);
-}
-
-static int
-nsc_calllen(nsc_call_t *in)
-{
- switch (MASKUPDATEBIT(in->nsc_callnumber)) {
-
- case GETPWUID:
- case GETGRGID:
- case NULLCALL:
- return (sizeof (*in));
-
- case GETPWNAM:
- case GETGRNAM:
- case GETHOSTBYNAME:
- return (sizeof (*in) + strlen(in->nsc_u.name));
- case GETIPNODEBYNAME:
- return (sizeof (*in) + strlen(in->nsc_u.ipnode.name));
-
- case GETHOSTBYADDR:
- case GETIPNODEBYADDR:
- return (sizeof (*in) + in->nsc_u.addr.a_length);
-
- case GETEXECID:
- case GETPROFNAM:
- case GETUSERNAM:
-
- return (sizeof (*in) + strlen(in->nsc_u.name));
- }
-
- return (0);
-}
-
-static int
-client_getadmin(admin_t *ptr)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = GETADMIN;
- ndata = sizeof (u);
- adata = sizeof (u.data);
- dptr = &u.data;
-
- if (_nsc_trydoorcall(&dptr, &ndata, &adata) != SUCCESS) {
- return (-1);
- }
-
- (void) memcpy(ptr, dptr->nsc_ret.nsc_u.buff, sizeof (*ptr));
- return (0);
-}
-
-/*ARGSUSED*/
-static void
-getadmin(nsc_return_t *out, int size, nsc_call_t *ptr)
-{
- out->nsc_return_code = SUCCESS;
- out->nsc_bufferbytesused = sizeof (current_admin);
- (void) memcpy(out->nsc_u.buff, &current_admin, sizeof (current_admin));
-}
-
-
-static int
-nscd_set_rbac(admin_t *new_admin, int invalidate)
-{
- int i;
- char *dbname = NULL;
- nsc_stat_t *cache = NULL;
- nsc_stat_t *new = NULL;
- void (*invalidate_func)(void);
-
-
- for (i = 1; i <= 3; i++) {
- /*
- * Three of the RBAC databases are cached.
- */
- switch (i) {
- case 1:
- dbname = NSS_DBNAM_EXECATTR;
- cache = &current_admin.exec;
- new = &new_admin->exec;
- invalidate_func = getexec_invalidate;
- break;
- case 2:
- dbname = NSS_DBNAM_PROFATTR;
- cache = &current_admin.prof;
- new = &new_admin->prof;
- invalidate_func = getprof_invalidate;
- break;
- case 3:
- dbname = NSS_DBNAM_USERATTR;
- cache = &current_admin.user;
- new = &new_admin->user;
- invalidate_func = getuser_invalidate;
- break;
- default:
- break;
- }
-
- if (invalidate) {
- if (new->nsc_invalidate) {
- logit("Invalidating %s cache\n", dbname);
- (*invalidate_func)();
- }
- } else {
- if (nscd_set_ttl_positive(cache, dbname,
- new->nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(cache, dbname,
- new->nsc_neg_ttl) < 0 ||
- nscd_set_khc(cache, dbname, new->nsc_keephot) < 0 ||
- nscd_set_odo(cache, dbname,
- new->nsc_old_data_ok) < 0 ||
- nscd_set_ec(cache, dbname, new->nsc_enabled) < 0 ||
- nscd_set_ss(cache, dbname,
- new->nsc_suggestedsize) < 0)
- return (-1);
- }
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-setadmin(nsc_return_t *out, int size, nsc_call_t *ptr)
-{
- admin_t *new;
-
- out->nsc_return_code = SUCCESS;
- out->nsc_bufferbytesused = sizeof (nsc_return_t);
-
- new = (admin_t *)ptr->nsc_u.name;
-
-
- /*
- * global admin stuff
- */
-
- if ((nscd_set_lf(&current_admin, new->logfile) < 0) ||
- nscd_set_dl(&current_admin, new->debug_level) < 0) {
- out->nsc_return_code = NOTFOUND;
- return (-1);
- }
-
- /*
- * per cache items
- */
-
- if (new->passwd.nsc_invalidate) {
- logit("Invalidating passwd cache\n");
- getpw_invalidate();
- }
-
- if (new->group.nsc_invalidate) {
- logit("Invalidating group cache\n");
- getgr_invalidate();
- }
-
- if (new->host.nsc_invalidate) {
- logit("Invalidating host cache\n");
- gethost_invalidate();
- }
-
- if (new->node.nsc_invalidate) {
- logit("Invalidating ipnodes cache\n");
- getnode_invalidate();
- }
-
- (void) nscd_set_rbac(new, 1); /* invalidate rbac cache */
-
- if (nscd_set_ttl_positive(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.group,
- "group",
- new->group.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.group,
- "group",
- new->group.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.group,
- "group",
- new->group.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.group,
- "group",
- new->group.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.group,
- "group",
- new->group.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.group,
- "group",
- new->group.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.node,
- "ipnodes",
- new->node.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.node,
- "ipnodes",
- new->node.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.node,
- "ipnodes",
- new->node.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.node,
- "ipnodes",
- new->node.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.node,
- "ipnodes",
- new->node.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.node,
- "ipnodes",
- new->node.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.host,
- "hosts",
- new->host.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.host,
- "hosts",
- new->host.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.host,
- "hosts",
- new->host.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.host,
- "hosts",
- new->host.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.host,
- "hosts",
- new->host.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.host,
- "hosts",
- new->host.nsc_suggestedsize) < 0 ||
- nscd_set_rbac(new, 0) < 0) {
- out->nsc_return_code = NOTFOUND;
- return (-1);
- }
- out->nsc_return_code = SUCCESS;
- return (0);
-}
-
-void
-client_killserver(void)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = KILLSERVER;
-
- ndata = sizeof (u);
- adata = sizeof (nsc_call_t);
-
- dptr = &u.data;
-
- _nsc_trydoorcall(&dptr, &ndata, &adata);
-}
-
-
-static int
-client_setadmin(admin_t *ptr)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = SETADMIN;
-
- (void) memcpy(u.data.nsc_call.nsc_u.name, ptr, sizeof (*ptr));
-
- ndata = sizeof (u);
- adata = sizeof (*ptr);
-
- dptr = &u.data;
-
- if (_nsc_trydoorcall(&dptr, &ndata, &adata) != SUCCESS) {
- return (-1);
- }
-
- return (0);
-}
-
-static void
-dump_stat(nsc_stat_t *ptr)
-{
- double hitrate;
- (void) printf("%10s cache is enabled\n",
- (ptr->nsc_enabled?"Yes":"No"));
- (void) printf("%10d cache hits on positive entries\n",
- ptr->nsc_pos_cache_hits);
- (void) printf("%10d cache hits on negative entries\n",
- ptr->nsc_neg_cache_hits);
- (void) printf("%10d cache misses on positive entries\n",
- ptr->nsc_pos_cache_misses);
- (void) printf("%10d cache misses on negative entries\n",
- ptr->nsc_neg_cache_misses);
- hitrate = ptr->nsc_pos_cache_misses + ptr->nsc_neg_cache_misses +
- ptr->nsc_pos_cache_hits + ptr->nsc_neg_cache_hits;
-
- if (hitrate > 0.0)
- hitrate = (100.0 * ((double)ptr->nsc_pos_cache_hits +
- (double)ptr->nsc_neg_cache_hits))/hitrate;
-
- (void) printf("%10.1f%% cache hit rate\n", hitrate);
- (void) printf("%10d queries deferred\n", ptr->nsc_throttle_count);
- (void) printf("%10d total entries\n", ptr->nsc_entries);
- (void) printf("%10d complete cache invalidations\n",
- ptr->nsc_invalidate_count);
- (void) printf("%10d suggested size\n", ptr->nsc_suggestedsize);
- (void) printf("%10d seconds time to live for positive entries\n",
- ptr->nsc_pos_ttl);
- (void) printf("%10d seconds time to live for negative entries\n",
- ptr->nsc_neg_ttl);
- (void) printf("%10d most active entries to be kept valid\n",
- ptr->nsc_keephot);
- (void) printf("%10s check /etc/{passwd, group, hosts, inet/ipnodes} "
- "file for changes\n",
- (ptr->nsc_check_files?"Yes":"No"));
-
- (void) printf("%10s use possibly stale data rather than waiting for "
- "refresh\n",
- (ptr->nsc_old_data_ok?"Yes":"No"));
-}
-
-static void
-client_showstats(admin_t *ptr)
-{
-
- (void) printf("nscd configuration:\n\n");
- (void) printf("%10d server debug level\n", ptr->debug_level);
- (void) printf("\"%s\" is server log file\n", ptr->logfile);
-
- (void) printf("\npasswd cache:\n\n");
- dump_stat(&(ptr->passwd));
- (void) printf("\ngroup cache:\n\n");
- dump_stat(&(ptr->group));
- (void) printf("\nhosts cache:\n\n");
- dump_stat(&(ptr->host));
- (void) printf("\nipnodes cache:\n\n");
- dump_stat(&(ptr->node));
- (void) printf("\nexec_attr cache:\n\n");
- dump_stat(&(ptr->exec));
- (void) printf("\nprof_attr cache:\n\n");
- dump_stat(&(ptr->prof));
- (void) printf("\nuser_attr cache:\n\n");
- dump_stat(&(ptr->user));
-}
-
-
-
/*
* detach from tty
*/
static void
detachfromtty(void)
{
- if (logfd > 0) {
+ nscd_rc_t rc;
+ char *me = "detachfromtty";
+
+ if (_logfd > 0) {
int i;
- for (i = 0; i < logfd; i++)
+ for (i = 0; i < _logfd; i++)
(void) close(i);
- closefrom(logfd+1);
+ closefrom(_logfd + 1);
} else
closefrom(0);
@@ -1899,9 +516,16 @@ detachfromtty(void)
switch (fork1()) {
case (pid_t)-1:
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to fork: pid = %d, %s\n",
+ getpid(), strerror(errno));
+
exit(1);
break;
case 0:
+ /* start the forker nscd if so configured */
+ _nscd_start_forker(saved_execname, saved_argc, saved_argv);
break;
default:
exit(0);
@@ -1909,5 +533,17 @@ detachfromtty(void)
(void) setsid();
(void) open("/dev/null", O_RDWR, 0);
(void) dup(0);
- (void) dup(0);
+ if (_logfd != 2)
+ (void) dup(0);
+
+ /*
+ * start monitoring the states of the name service clients
+ */
+ rc = _nscd_init_smf_monitor();
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to start the SMF monitor (rc = %d)\n", rc);
+
+ exit(-1);
+ }
}
diff --git a/usr/src/cmd/nscd/svc-nscd b/usr/src/cmd/nscd/svc-nscd
index a611923be4..08a856ee66 100644
--- a/usr/src/cmd/nscd/svc-nscd
+++ b/usr/src/cmd/nscd/svc-nscd
@@ -20,6 +20,7 @@
#
# CDDL HEADER END
#
+#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -56,14 +57,7 @@ if (smf_is_system_labeled); then
fi
if [ -f /etc/nscd.conf -a -f /usr/sbin/nscd ]; then
- secure=""
-
- if egrep -s "^(passwd|passwd_compat):.*nisplus" /etc/nsswitch.conf
- then
- /usr/lib/nscd_nischeck passwd || secure=" -S passwd,yes"
- fi
-
- /usr/sbin/nscd$secure < /dev/null > /dev/msglog 2>&1 &
+ /usr/sbin/nscd < /dev/null > /dev/msglog 2>&1 &
else
echo "No /etc/nscd.conf or no /usr/sbin/nscd"
exit $SMF_EXIT_ERR_CONFIG
diff --git a/usr/src/cmd/rpcsvc/nis/utils/nisaddent.c b/usr/src/cmd/rpcsvc/nis/utils/nisaddent.c
index 4e92c45d05..6c9c95ee1a 100644
--- a/usr/src/cmd/rpcsvc/nis/utils/nisaddent.c
+++ b/usr/src/cmd/rpcsvc/nis/utils/nisaddent.c
@@ -1396,7 +1396,7 @@ genent_hosts6(line, cback, udata)
eobj.EN_data.en_cols.en_cols_val = ecol;
eobj.EN_data.en_cols.en_cols_len = 4;
- if (cback != NULL)
+ if (cback == NULL)
cback = addentry;
/*
diff --git a/usr/src/head/nss_common.h b/usr/src/head/nss_common.h
index 5582bacd48..d2fa459d39 100644
--- a/usr/src/head/nss_common.h
+++ b/usr/src/head/nss_common.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1992-1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
/*
@@ -49,9 +48,9 @@ extern "C" {
*
* From nsswitch.conf(4):
*
- * The operating system uses a number of ``databases'' of information
+ * The operating system uses a number of "databases" of information
* about hosts, users (passwd/shadow), groups and so forth. Data for
- * these can come from a variety of ``sources'': host-names and
+ * these can come from a variety of "sources": host-names and
* -addresses, for example, may be found in /etc/hosts, NIS, NIS+ or
* DNS. One or more sources may be used for each database; the
* sources and their lookup order are specified in the
@@ -59,16 +58,20 @@ extern "C" {
*
* The implementation of this consists of:
*
- * - a ``frontend'' for each database, which provides a programming
+ * - a "frontend" for each database, which provides a programming
* interface for that database [for example, the "passwd" frontend
* consists of getpwnam_r(), getpwuid_r(), getpwent_r(), setpwent(),
* endpwent(), and the old MT-unsafe routines getpwnam() and getpwuid()]
* and is implemented by calls to...
*
- * - the common core of the switch (``switch engine''); it determines
- * which sources to use and invokes...
+ * - the common core of the switch (called the "switch" or "policy" engine);
+ * that determines what sources to use and when to invoke them. This
+ * component works in conjunction with the name service switch (nscd).
+ * Usually nscd is the policy engine for an application lookup.
*
- * - A ``backend'' for each useful <database, source> pair. Each backend
+ * - Old style backend interfaces follow this pointer to function interface:
+ *
+ * A "backend" exists for useful <database, source> pairs. Each backend
* consists of whatever private data it needs and a set of functions
* that the switch engine may invoke on behalf of the frontend
* [e.g. the "nis" backend for "passwd" provides routines to lookup
@@ -78,13 +81,15 @@ extern "C" {
* all its backends. The switch engine knows as little as possible
* about these interfaces.
*
- * (The term ``backend'' is used ambiguously; it may also refer to a
+ * (The term "backend" is used ambiguously; it may also refer to a
* particular instantiation of a backend, or to the set of all backends
* for a particular source, e.g. "the nis backend").
*
* This header file defines the interface between the switch engine and the
* frontends and backends. Interfaces between specific frontends and
* backends are defined elsewhere; many are in <nss_dbdefs.h>.
+ * Most of these definitions are in the form of pointer to function
+ * indicies used to call specific backend APIs.
*
*
* Switch-engine outline
@@ -102,24 +107,29 @@ extern "C" {
*
* (1) getpwnam_r fills in (getpwnam-specific) argument/result struct,
* calls nss_search(),
- * (2) nss_search looks up configuration info, gets "passwd: files nis",
- * (3) nss_search decides to try first source ("files"),
+ * (2) nss_search queries the name service cache for an existing
+ * result via a call to _nsc_search(). if the cache
+ * (nscd) has a definitive answer skip to step 7
+ * (3) nss_search looks up configuration info, gets "passwd: files nis",
+ * (4) nss_search decides to try first source ("files"),
* (a) nss_search locates code for <"passwd", "files"> backend,
* (b) nss_search creates instance of backend,
* (c) nss_search calls get-by-name routine in backend,
+ * through a function pointer interface,
* (d) backend searches /etc/passwd, doesn't find the name,
* returns "not found" status to nss_search,
- * (4) nss_search examines status and config info, decides to try
+ * (5) nss_search examines status and config info, decides to try
* next source ("nis"),
* (a) nss_search locates code for <"passwd", "nis"> backend,
* (b) nss_search creates instance of backend,
* (c) nss_search calls get-by-name routine in backend,
+ * through a function pointer interface,
* (d) backend searches passwd.byname, finds the desired entry,
* fills in the result part of the getpwnam-specific
* struct, returns "success" status to nss_search,
- * (5) nss_search examines status and config info, decides to return
+ * (6) nss_search examines status and config info, decides to return
* to caller,
- * (6) getpwnam_r extracts result from getpwnam-specific struct,
+ * (7) getpwnam_r extracts result from getpwnam-specific struct,
* returns to caller.
*
*
@@ -167,7 +177,6 @@ extern "C" {
* give per-invocation state.
*/
-
/*
* Backend instances
* -----------------
@@ -191,19 +200,50 @@ extern "C" {
* structure (the contents are opaque to the switch engine).
* The four well-known functions ignore the (void *) pointer.
*
- * Backend routines return one of five status codes to the switch engine:
+ * Backend routines return the following status codes to the switch engine:
+ *
* SUCCESS, UNAVAIL, NOTFOUND, TRYAGAIN (these are the same codes that may
- * be specified in the config information; see nsswitch.conf(4)), or
+ * be specified in the config information; see nsswitch.conf(4))
+ *
+ * The remaining conditions/errors are internally generated and if
+ * necessary are translated, as to one of the above external errors,
+ * usually NOTFOUND or UNAVAIL.
+ *
* NSS_NISSERVDNS_TRYAGAIN (should only be used by the NIS backend for
* NIS server in DNS forwarding mode to indicate DNS server non-response).
+ *
+ * The policy component may return NSS_TRYLOCAL which signifies that nscd
+ * is not going to process the request, and it should be performed locally.
+ *
+ * NSS_ERROR is a catchall for internal error conditions, errno will be set
+ * to a system <errno.h> error that can help track down the problem if
+ * it is persistent. This error is the result of some internal error
+ * condition and should not be seen during or exposed to aan application.
+ * The error may be from the application side switch component or from the
+ * nscd side switch component.
+ *
+ * NSS_ALTRETRY and NSS_ALTRESET are internal codes used by the application
+ * side policy component and nscd to direct the policy component to
+ * communicate to a per-user nscd if/when per-user authentication is enabled.
+ *
+ * NSS_NSCD_PRIV is a catchall for internal nscd errors or status
+ * conditions. This return code is not visible to applications. nscd
+ * may use this as a status flag and maintain additional error or status
+ * information elsewhere in other private nscd data. This status value
+ * is for nscd private/internal use only.
*/
typedef enum {
- NSS_SUCCESS,
- NSS_NOTFOUND,
- NSS_UNAVAIL,
- NSS_TRYAGAIN,
- NSS_NISSERVDNS_TRYAGAIN
+ NSS_SUCCESS = 0,
+ NSS_NOTFOUND = 1,
+ NSS_UNAVAIL = 2,
+ NSS_TRYAGAIN = 3,
+ NSS_NISSERVDNS_TRYAGAIN = 4,
+ NSS_TRYLOCAL = 5,
+ NSS_ERROR = 6,
+ NSS_ALTRETRY = 7,
+ NSS_ALTRESET = 8,
+ NSS_NSCD_PRIV = 9
} nss_status_t;
struct nss_backend;
@@ -256,11 +296,11 @@ typedef int nss_dbop_t;
*/
#if defined(__STDC__)
-typedef nss_backend_t * (*nss_backend_constr_t)(const char *db_name,
+typedef nss_backend_t *(*nss_backend_constr_t)(const char *db_name,
const char *src_name,
/* Hook for (unimplemented) args in nsswitch.conf */ const char *cfg_args);
#else
-typedef nss_backend_t * (*nss_backend_constr_t)();
+typedef nss_backend_t *(*nss_backend_constr_t)();
#endif
struct nss_backend_finder {
@@ -342,6 +382,20 @@ typedef void (*nss_db_initf_t)();
#endif
/*
+ * DBD param offsets in NSS2 nscd header.
+ * Offsets are relative to beginning of dbd section.
+ * 32 bit offsets should be sufficient, forever.
+ * 0 offset == NULL
+ * flags == nss_dbp_flags
+ */
+typedef struct nss_dbd {
+ uint32_t o_name;
+ uint32_t o_config_name;
+ uint32_t o_default_config;
+ uint32_t flags;
+} nss_dbd_t;
+
+/*
* These structures are defined inside the implementation of the switch
* engine; the interface just holds pointers to them.
*/
@@ -369,22 +423,81 @@ typedef struct {
#define NSS_GETENT_INIT { 0, DEFAULTMUTEX }
#define DEFINE_NSS_GETENT(name) nss_getent_t name = NSS_GETENT_INIT
+/*
+ * Policy Engine Configuration
+ * ---------------------------
+ *
+ * When nscd is running it can reconfigure it's internal policy engine
+ * as well as advise an application's front-end and policy engine on how
+ * respond optimally to results being returned from nscd. This is done
+ * through the policy engine configuration interface.
+ */
+
+typedef enum {
+ NSS_CONFIG_GET,
+ NSS_CONFIG_PUT,
+ NSS_CONFIG_ADD,
+ NSS_CONFIG_DELETE,
+ NSS_CONFIG_LIST
+} nss_config_op_t;
+
+struct nss_config {
+ char *name;
+ nss_config_op_t cop;
+ mutex_t *lock;
+ void *buffer;
+ size_t length;
+};
+typedef struct nss_config nss_config_t;
+
+
#if defined(__STDC__)
+extern nss_status_t nss_config(nss_config_t **, int);
+
extern nss_status_t nss_search(nss_db_root_t *, nss_db_initf_t,
int search_fnum, void *search_args);
extern nss_status_t nss_getent(nss_db_root_t *, nss_db_initf_t, nss_getent_t *,
void *getent_args);
extern void nss_setent(nss_db_root_t *, nss_db_initf_t, nss_getent_t *);
-
extern void nss_endent(nss_db_root_t *, nss_db_initf_t, nss_getent_t *);
- /* ^^ superfluous but consistent */
extern void nss_delete(nss_db_root_t *);
+
+extern nss_status_t nss_pack(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t, int, void *);
+extern nss_status_t nss_pack_ent(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t, nss_getent_t *);
+extern nss_status_t nss_unpack(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t, int, void *);
+extern nss_status_t nss_unpack_ent(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t, nss_getent_t *, void *);
+
+extern nss_status_t _nsc_search(nss_db_root_t *, nss_db_initf_t,
+ int search_fnum, void *search_args);
+extern nss_status_t _nsc_getent_u(nss_db_root_t *, nss_db_initf_t,
+ nss_getent_t *, void *getent_args);
+extern nss_status_t _nsc_setent_u(nss_db_root_t *, nss_db_initf_t,
+ nss_getent_t *);
+extern nss_status_t _nsc_endent_u(nss_db_root_t *, nss_db_initf_t,
+ nss_getent_t *);
+
#else
+extern nss_status_t nss_config();
+
extern nss_status_t nss_search();
extern nss_status_t nss_getent();
extern void nss_setent();
extern void nss_endent();
extern void nss_delete();
+
+extern int nss_pack();
+extern int nss_pack_ent();
+extern int nss_unpack();
+extern int nss_unpack_ent();
+
+extern nss_status_t _nsc_search();
+extern nss_status_t _nsc_getent_u();
+extern nss_status_t _nsc_setent_u();
+extern nss_status_t _nsc_endent_u();
#endif
#ifdef __cplusplus
diff --git a/usr/src/head/nss_dbdefs.h b/usr/src/head/nss_dbdefs.h
index dc37584a46..fa4dd6525e 100644
--- a/usr/src/head/nss_dbdefs.h
+++ b/usr/src/head/nss_dbdefs.h
@@ -40,6 +40,8 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/types.h>
+#include <unistd.h>
#include <errno.h>
#include <netdb.h> /* MAXALIASES, MAXADDRS */
#include <limits.h> /* LOGNAME_MAX */
@@ -209,12 +211,17 @@ extern "C" {
#define NSS_BUFLEN_USERATTR ((NSS_BUFLEN_ATTRDB) * 8)
#define NSS_BUFLEN_TSOL NSS_LINELEN_TSOL
-
#define NSS_BUFLEN_TSOL_TP NSS_BUFLEN_TSOL
#define NSS_BUFLEN_TSOL_RH NSS_BUFLEN_TSOL
#define NSS_BUFLEN_TSOL_ZC NSS_BUFLEN_TSOL
/*
+ * Default cache door buffer size (2x largest buffer)
+ */
+
+#define NSS_BUFLEN_DOOR ((NSS_BUFSIZ) * 16)
+
+/*
* Arguments and results, passed between the frontends and backends for
* the well-known databases. The getXbyY_r() and getXent_r() routines
* use a common format that is further described below; other routines
@@ -222,6 +229,26 @@ extern "C" {
*/
/*
+ * The nss_str2ent_t routine is the data marshaller for the nsswitch.
+ * it converts 'native files' format into 'entry' format as part of the
+ * return processing for a getXbyY interface.
+ *
+ * The nss_groupstr_t routine does the real work for any backend
+ * that can supply a netgroup entry as a string in /etc/group format
+ */
+#if defined(__STDC__)
+typedef int (*nss_str2ent_t)(const char *in, int inlen,
+ void *ent, char *buf, int buflen);
+
+struct nss_groupsbymem; /* forward definition */
+typedef nss_status_t (*nss_groupstr_t)(const char *instr, int inlen,
+ struct nss_groupsbymem *);
+#else
+typedef int (*nss_str2ent_t)();
+typedef nss_status_t (*nss_groupstr_t)();
+#endif
+
+/*
* The initgroups() function [see initgroups(3c)] needs to find all the
* groups to which a given user belongs. To do this it calls
* _getgroupsbymember(), which is part of the frontend for the "group"
@@ -248,21 +275,8 @@ struct nss_groupsbymem { /* For _getgroupsbymember() */
gid_t *gid_array;
int maxgids;
int force_slow_way;
- /*
- * The process_cstr() routine does the real work for any backend
- * that can supply a group entry as a string in /etc/group format
- */
-#if defined(__STDC__)
- int (*str2ent) (const char *instr,
- int instr_len,
- void *ent, char *buffer, int buflen);
- nss_status_t (*process_cstr) (const char *instr,
- int instr_len,
- struct nss_groupsbymem *);
-#else
- int (*str2ent)();
- nss_status_t (*process_cstr)();
-#endif
+ nss_str2ent_t str2ent;
+ nss_groupstr_t process_cstr;
/* in_out: */
int numgids;
@@ -305,16 +319,16 @@ struct nss_groupsbymem { /* For _getgroupsbymember() */
*/
enum nss_netgr_argn { /* We need (machine, user, domain) triples */
- NSS_NETGR_MACHINE,
- NSS_NETGR_USER,
- NSS_NETGR_DOMAIN,
- NSS_NETGR_N
+ NSS_NETGR_MACHINE = 0,
+ NSS_NETGR_USER = 1,
+ NSS_NETGR_DOMAIN = 2,
+ NSS_NETGR_N = 3
};
enum nss_netgr_status { /* Status from setnetgrent, multi_innetgr */
- NSS_NETGR_FOUND,
- NSS_NETGR_NO,
- NSS_NETGR_NOMEM
+ NSS_NETGR_FOUND = 0,
+ NSS_NETGR_NO = 1,
+ NSS_NETGR_NOMEM = 2
};
struct nss_setnetgrent_args {
@@ -349,7 +363,6 @@ struct nss_innetgr_args {
enum nss_netgr_status status;
};
-
/*
* nss_XbyY_buf_t -- structure containing the generic arguments passwd to
* getXXXbyYYY_r() and getXXXent_r() routines. The (void *) value points to
@@ -376,7 +389,7 @@ extern void _nss_XbyY_buf_free();
#define NSS_XbyY_ALLOC(bufpp, str_size, buf_size) (\
(*bufpp) == 0 \
? (*bufpp) = _nss_XbyY_buf_alloc(str_size, buf_size) \
- : (*bufpp)) \
+ : (*bufpp))
#define NSS_XbyY_FREE(bufpp) (_nss_XbyY_buf_free(*bufpp), (*bufpp) = 0)
@@ -406,7 +419,7 @@ extern void _nss_XbyY_buf_free();
* in parsing and marshalling these into the buffer.
*/
-union nss_XbyY_key { /* No tag; backend should know what to expect */
+typedef union nss_XbyY_key { /* No tag; backend should know what to expect */
uid_t uid;
gid_t gid;
projid_t projid;
@@ -439,7 +452,16 @@ union nss_XbyY_key { /* No tag; backend should know what to expect */
int flags;
} ipnode;
void *attrp; /* for the new attr databases */
-};
+} nss_XbyY_key_t;
+
+
+#if defined(__STDC__)
+typedef int (*nss_key2str_t)(void *buffer, size_t buflen,
+ nss_XbyY_key_t *key, size_t *len);
+#else
+typedef int (*nss_key2str_t)();
+#endif
+
typedef struct nss_XbyY_args {
@@ -451,22 +473,187 @@ typedef struct nss_XbyY_args {
* Used only in hosts, protocols,
* networks, rpc, and services.
*/
-#if defined(__STDC__)
- int (*str2ent) (const char *instr,
- int instr_len,
- void *ent, char *buffer, int buflen);
-#else
- int (*str2ent)();
-#endif
+ nss_str2ent_t str2ent;
union nss_XbyY_key key;
/* OUT */
void *returnval;
int erange;
- int h_errno; /* For gethost*_r() */
- nss_status_t status; /* from the backend last called */
+ int h_errno; /* For gethost*_r() */
+ nss_status_t status; /* from the backend last called */
+/* NSS2 */
+ nss_key2str_t key2str; /* IN */
+ size_t returnlen; /* OUT */
+
+/* NSCD/DOOR data */
+
+/* ... buffer arena follows... */
} nss_XbyY_args_t;
+
+
+/*
+ * nss/nscd v2 interface, packed buffer format
+ *
+ * A key component of the v2 name service switch is the redirection
+ * of all activity to nscd for actual processing. In the original
+ * switch most activity took place in each application, and the nscd
+ * cache component was an add-on optional interface.
+ *
+ * The nscd v1 format was a completely private interface that
+ * implemented specific bufferiing formats on a per getXbyY API basis.
+ *
+ * The nss/nscd v2 interface uses a common header and commonalizes
+ * the buffering format as consistently as possible. The general rule
+ * of thumb is that backends are required to assemble their results in
+ * "files based" format [IE the format used on a per result basis as
+ * returned by the files backend] and then call the standard str2ent
+ * interface. This is the original intended design as used in the files
+ * and nis backends.
+ *
+ * The benefit of this is that the application side library can assemble
+ * a request and provide a header and a variable length result buffer via
+ * a doors API, and then the nscd side switch can assemble a a getXbyY
+ * request providing the result buffer and a str2ent function that copies
+ * but does not unpack the result.
+ *
+ * This results is returned back via the door, and unpacked using the
+ * native library side str2ent interface.
+ *
+ * Additionally, the common header allows extensibility to add new
+ * getXbyYs, putXbyYs or other maintenance APIs to/from nscd without
+ * changing the existing "old style" backend interfaces.
+ *
+ * Finally new style getXbyY, putXbyY and backend interfaces can be
+ * by adding new operation requests to the header, while old style
+ * backwards compatability.
+ */
+
+/*
+ * nss/nscd v2 callnumber definitions
+ */
+
+/*
+ * callnumbers are separated by categories, such as:
+ * application to nscd requests, nscd to nscd requests,
+ * smf to nscd requests, etc.
+ */
+
+#define NSCDV2CATMASK (0xFF000000)
+#define NSCDV2CALLMASK (0x00FFFFFF)
+
+/*
+ * nss/nscd v2 categories
+ */
+
+#define NSCD_CALLCAT_APP ('a'<<24)
+#define NSCD_CALLCAT_N2N ('n'<<24)
+
+/* nscd v2 app-> nscd callnumbers */
+
+#define NSCD_SEARCH (NSCD_CALLCAT_APP|0x01)
+#define NSCD_SETENT (NSCD_CALLCAT_APP|0x02)
+#define NSCD_GETENT (NSCD_CALLCAT_APP|0x03)
+#define NSCD_ENDENT (NSCD_CALLCAT_APP|0x04)
+#define NSCD_PUT (NSCD_CALLCAT_APP|0x05)
+#define NSCD_GETHINTS (NSCD_CALLCAT_APP|0x06)
+
+/* nscd v2 SETENT cookie markers */
+
+#define NSCD_NEW_COOKIE 0
+#define NSCD_LOCAL_COOKIE 1
+
+/* nscd v2 header revision */
+/* treated as 0xMMMMmmmm MMMM - Major Rev, mmmm - Minor Rev */
+
+#define NSCD_HEADER_REV 0x00020000
+
+/*
+ * ptr/uint data type used to calculate shared nscd buffer struct sizes
+ * sizes/offsets are arbitrarily limited to 32 bits for 32/64 compatibility
+ * datatype is 64 bits for possible pointer storage and future use
+ */
+
+typedef uint64_t nssuint_t;
+
+/*
+ * nscd v2 buffer layout overview
+ *
+ * The key interface to nscd moving forward is the doors interface
+ * between applications and nscd (NSCD_CALLCAT_APP), and nscd and
+ * it's children (NSCD_CALLCAT_N2N).
+ *
+ * Regardless of the interface used, the buffer layout is consistent.
+ * The General Layout is:
+ * [nss_pheader_t][IN key][OUT data results]{extend results}
+ *
+ * The header (nss_pheader_t) remains constant.
+ * Keys and key layouts vary between call numbers/requests
+ * NSCD_CALLCAT_APP use key layouts mimics/defines in nss_dbdefs.h
+ * NSCD_CALLCAT_NSN use layouts defined by nscd headers
+ * Data and data results vary between results
+ * NSCD_CALLCAT_APP return "file standard format" output buffers
+ * NSCD_CALLCAT_NSN return data defined by nscd headers
+ * extended results are optional and vary
+ *
+ */
+
+/*
+ * nss_pheader_t -- buffer header structure that contains switch data
+ * "packed" by the client into a buffer suitable for transport over
+ * nscd's door, and that can be unpacked into a native form within
+ * nscd's switch. Capable of packing and unpacking data ans results.
+ *
+ * NSCD_HEADER_REV: 0x00020000 16 x uint64 = (128 byte header)
+ */
+
+typedef struct {
+ uint32_t nsc_callnumber; /* packed buffer request */
+ uint32_t nss_dbop; /* old nss dbop */
+ uint32_t p_ruid; /* real uid */
+ uint32_t p_euid; /* effective uid */
+ uint32_t p_version; /* 0xMMMMmmmm Major/minor */
+ uint32_t p_status; /* nss_status_t */
+ uint32_t p_errno; /* errno */
+ uint32_t p_herrno; /* h_errno */
+ nssuint_t libpriv; /* reserved (for lib/client) */
+ nssuint_t pbufsiz; /* buffer size */
+ nssuint_t dbd_off; /* IN: db desc off */
+ nssuint_t dbd_len; /* IN: db desc len */
+ nssuint_t key_off; /* IN: key off */
+ nssuint_t key_len; /* IN: key len */
+ nssuint_t data_off; /* OUT: data off */
+ nssuint_t data_len; /* OUT: data len */
+ nssuint_t ext_off; /* OUT: extended results off */
+ nssuint_t ext_len; /* OUT: extended results len */
+ nssuint_t nscdpriv; /* reserved (for nscd) */
+ nssuint_t reserved1; /* reserved (TBD) */
+} nss_pheader_t;
+
+/*
+ * nss_pnetgr_t -- packed offset structure for holding keys used
+ * by innetgr (__multi_innetgr) key
+ * Key format is:
+ * nss_pnetgr_t
+ * (nssuint_t)[machine_argc] offsets to strings
+ * (nssuint_t)[user_argc] offsets to strings
+ * (nssuint_t)[domain_argc] offsets to strings
+ * (nssuint_t)[groups_argc] offsets to strings
+ * machine,user,domain,groups strings
+ */
+
+typedef struct {
+ uint32_t machine_argc;
+ uint32_t user_argc;
+ uint32_t domain_argc;
+ uint32_t groups_argc;
+ nssuint_t machine_offv;
+ nssuint_t user_offv;
+ nssuint_t domain_offv;
+ nssuint_t groups_offv;
+} nss_pnetgr_t;
+
+
/* status returned by the str2ent parsing routines */
#define NSS_STR_PARSE_SUCCESS 0
#define NSS_STR_PARSE_PARSE 1
@@ -478,18 +665,51 @@ typedef struct nss_XbyY_args {
(str)->buf.buflen = (len), \
(str)->stayopen = 0, \
(str)->str2ent = (func), \
+ (str)->key2str = NULL, \
(str)->returnval = 0, \
+ (str)->returnlen = 0, \
+ (str)->erange = 0)
+
+#define NSS_XbyY_INIT_EXT(str, res, bufp, len, func, kfunc) (\
+ (str)->buf.result = (res), \
+ (str)->buf.buffer = (bufp), \
+ (str)->buf.buflen = (len), \
+ (str)->stayopen = 0, \
+ (str)->str2ent = (func), \
+ (str)->key2str = (kfunc), \
+ (str)->returnval = 0, \
+ (str)->returnlen = 0, \
(str)->erange = 0)
#define NSS_XbyY_FINI(str) (\
(str)->returnval == 0 && (str)->erange && (errno = ERANGE), \
(str)->returnval)
+#define NSS_PACKED_CRED_CHECK(buf, ruid, euid) (\
+ ((nss_pheader_t *)(buf))->p_ruid == (ruid) && \
+ ((nss_pheader_t *)(buf))->p_euid == (euid))
+
#if defined(__STDC__)
-extern char **_nss_netdb_aliases
- (const char *, int, char *, int);
+extern char **_nss_netdb_aliases(const char *, int, char *, int);
+extern nss_status_t nss_default_key2str(void *, size_t, nss_XbyY_args_t *,
+ const char *, int, size_t *);
+extern nss_status_t nss_packed_arg_init(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t *, int *,
+ nss_XbyY_args_t *);
+extern nss_status_t nss_packed_context_init(void *, size_t, nss_db_root_t *,
+ nss_db_initf_t *, nss_getent_t **,
+ nss_XbyY_args_t *);
+extern void nss_packed_set_status(void *, size_t, nss_status_t,
+ nss_XbyY_args_t *);
+extern nss_status_t nss_packed_getkey(void *, size_t, char **, int *,
+ nss_XbyY_args_t *);
#else
extern char **_nss_netdb_aliases();
+extern int nss_default_key2str();
+extern nss_status_t nss_packed_arg_init();
+extern nss_status_t nss_packed_context_init();
+extern void nss_packed_set_status();
+extern nss_status_t nss_packed_getkey();
#endif
/*
@@ -497,6 +717,39 @@ extern char **_nss_netdb_aliases();
* destructor/endent/setent/getent are defined in <nss_common.h>
*/
+/*
+ * These are part of the "Over the wire" IE app->nscd getXbyY
+ * op for well known getXbyY's. Cannot use NSS_DBOP_X_Y directly
+ * because NSS_DBOP_next_iter is NOT an incrementing counter value
+ * it's a starting offset into an array value.
+ */
+
+#define NSS_DBOP_X(x) ((x)<<16)
+#define NSS_DBOP_XY(x, y) ((x)|(y))
+
+#define NSS_DBOP_ALIASES NSS_DBOP_X(1)
+#define NSS_DBOP_AUTOMOUNT NSS_DBOP_X(2)
+#define NSS_DBOP_BOOTPARAMS NSS_DBOP_X(3)
+#define NSS_DBOP_ETHERS NSS_DBOP_X(4)
+#define NSS_DBOP_GROUP NSS_DBOP_X(5)
+#define NSS_DBOP_HOSTS NSS_DBOP_X(6)
+#define NSS_DBOP_IPNODES NSS_DBOP_X(7)
+#define NSS_DBOP_NETGROUP NSS_DBOP_X(8)
+#define NSS_DBOP_NETMASKS NSS_DBOP_X(9)
+#define NSS_DBOP_NETWORKS NSS_DBOP_X(10)
+#define NSS_DBOP_PASSWD NSS_DBOP_X(11)
+#define NSS_DBOP_PRINTERS NSS_DBOP_X(12)
+#define NSS_DBOP_PROJECT NSS_DBOP_X(13)
+#define NSS_DBOP_PROTOCOLS NSS_DBOP_X(14)
+#define NSS_DBOP_PUBLICKEY NSS_DBOP_X(15)
+#define NSS_DBOP_RPC NSS_DBOP_X(16)
+#define NSS_DBOP_SERVICES NSS_DBOP_X(17)
+#define NSS_DBOP_AUDITUSER NSS_DBOP_X(18)
+#define NSS_DBOP_AUTHATTR NSS_DBOP_X(19)
+#define NSS_DBOP_EXECATTR NSS_DBOP_X(20)
+#define NSS_DBOP_PROFATTR NSS_DBOP_X(21)
+#define NSS_DBOP_USERATTR NSS_DBOP_X(22)
+
#define NSS_DBOP_GROUP_BYNAME (NSS_DBOP_next_iter)
#define NSS_DBOP_GROUP_BYGID (NSS_DBOP_GROUP_BYNAME + 1)
#define NSS_DBOP_GROUP_BYMEMBER (NSS_DBOP_GROUP_BYGID + 1)
diff --git a/usr/src/head/nss_netdir.h b/usr/src/head/nss_netdir.h
index f84bc07657..6c8988eabf 100644
--- a/usr/src/head/nss_netdir.h
+++ b/usr/src/head/nss_netdir.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1993-94, 1999, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
diff --git a/usr/src/head/nsswitch.h b/usr/src/head/nsswitch.h
index ecf4841cf9..f2657f135e 100644
--- a/usr/src/head/nsswitch.h
+++ b/usr/src/head/nsswitch.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1991-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
/*
@@ -31,7 +30,6 @@
* in <nss_common.h> should be used in preference to this.
*
* This is a Project Private interface. It may change in future releases.
- * ==== ^^^^^^^^^^^^^^^ ?
*/
#ifndef _NSSWITCH_H
@@ -43,7 +41,9 @@
extern "C" {
#endif
+#ifndef __NSW_CONFIG_FILE
#define __NSW_CONFIG_FILE "/etc/nsswitch.conf"
+#endif
#define __NSW_DEFAULT_FILE "/etc/default/nss"
#define __NSW_HOSTS_DB "hosts"
diff --git a/usr/src/lib/libc/inc/nsswitch_priv.h b/usr/src/lib/libc/inc/nsswitch_priv.h
index 70baa39fb3..65e2dd176e 100644
--- a/usr/src/lib/libc/inc/nsswitch_priv.h
+++ b/usr/src/lib/libc/inc/nsswitch_priv.h
@@ -33,7 +33,6 @@
* and contains new versions of the switch low level interface.
*
* This is a Project Private interface. It may change in future releases.
- * ==== ^^^^^^^^^^^^^^^ ?
*/
#ifndef _NSSWITCH_PRIV_H
diff --git a/usr/src/lib/libc/inc/tsd.h b/usr/src/lib/libc/inc/tsd.h
index 004dc82846..58042b983c 100644
--- a/usr/src/lib/libc/inc/tsd.h
+++ b/usr/src/lib/libc/inc/tsd.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,6 +28,10 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef enum {
_T_GETDATE = 0,
_T_WCSTOK,
@@ -55,6 +58,7 @@ typedef enum {
_T_PWBUF,
_T_GRBUF,
_T_SPBUF,
+ _T_DOORBUF,
_T_NUM_ENTRIES /* this *must* be the last member */
} __tsd_item_t;
@@ -63,4 +67,8 @@ typedef enum {
*/
extern void *tsdalloc(__tsd_item_t, size_t, void (*)(void *));
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LIBC_INC_TSD_H */
diff --git a/usr/src/lib/libc/port/gen/getgrnam_r.c b/usr/src/lib/libc/port/gen/getgrnam_r.c
index adaa8ce918..d1574b1985 100644
--- a/usr/src/lib/libc/port/gen/getgrnam_r.c
+++ b/usr/src/lib/libc/port/gen/getgrnam_r.c
@@ -48,8 +48,7 @@
#include <sys/mman.h>
extern int _getgroupsbymember(const char *, gid_t[], int, int);
-int str2group(const char *, int, void *,
- char *, int);
+int str2group(const char *, int, void *, char *, int);
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
@@ -66,10 +65,6 @@ _nss_initf_group(nss_db_params_t *p)
#include <getxby_door.h>
#include <sys/door.h>
-static struct group *
-process_getgr(struct group *result, char *buffer, int buflen,
- nsc_data_t *sptr, int ndata);
-
struct group *
_uncached_getgrnam_r(const char *name, struct group *result, char *buffer,
int buflen);
@@ -84,52 +79,17 @@ _uncached_getgrgid_r(gid_t gid, struct group *result, char *buffer, int buflen);
struct group *
_getgrnam_r(const char *name, struct group *result, char *buffer, int buflen)
{
- /*
- * allocate room on the stack for the nscd to return
- * group and group member information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct group *resptr = NULL;
-
- if ((name == (const char *)NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
- errno = ERANGE;
- return (NULL);
- }
-
- ndata = sizeof (space);
- adata = strlen(name) + sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETGRNAM;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
- sptr = &space.s_d;
+ nss_XbyY_args_t arg;
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
+ if (name == (const char *)NULL) {
+ errno = ERANGE;
return (NULL);
- default:
- return ((struct group *)_uncached_getgrnam_r(name, result,
- buffer, buflen));
}
-
- resptr = process_getgr(result, buffer, buflen, sptr, ndata);
-
- /*
- * check to see if doors reallocated memory underneath us
- * if they did munmap the memory or suffer a memory leak
- */
-
- if (sptr != &space.s_d)
- munmap((void *)sptr, ndata);
-
- return (resptr);
+ NSS_XbyY_INIT(&arg, result, buffer, buflen, str2group);
+ arg.key.name = name;
+ (void) nss_search(&db_root, _nss_initf_group,
+ NSS_DBOP_GROUP_BYNAME, &arg);
+ return ((struct group *)NSS_XbyY_FINI(&arg));
}
/*
@@ -139,186 +99,13 @@ _getgrnam_r(const char *name, struct group *result, char *buffer, int buflen)
struct group *
_getgrgid_r(gid_t gid, struct group *result, char *buffer, int buflen)
{
- /*
- * allocate room on the stack for the nscd to return
- * group and group member information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct group *resptr = NULL;
-
- ndata = sizeof (space);
- adata = sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETGRGID;
- space.s_d.nsc_call.nsc_u.gid = gid;
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- return (NULL);
- default:
- return ((struct group *)_uncached_getgrgid_r(gid, result,
- buffer, buflen));
- }
-
- resptr = process_getgr(result, buffer, buflen, sptr, ndata);
-
- /*
- * check to see if doors reallocated memory underneath us
- * if they did munmap the memory or suffer a memory leak
- */
-
- if (sptr != &space.s_d)
- munmap((void *)sptr, ndata);
-
- return (resptr);
-}
-/*
- * This routine should be rewritten - there's no reason it
- * cannot be the same code for 32 and 64 bit w/ a bit of care.
- */
-/* ARGSUSED4 */
-static struct group *
-process_getgr(struct group *result, char *buffer, int buflen,
- nsc_data_t *sptr, int ndata)
-{
- int i;
- char *fixed;
-#ifdef _LP64
- char *buffer32;
- char **gr_mem32;
- uptr32_t index;
- struct group group64;
-#endif /* _LP64 */
-
-/* align buffer on a pointer boundry 4bytes in 32bits and 8 bytes in 64bits */
-#ifdef _LP64
- fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
-#else
- fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
-#endif /* _LP64 */
-
- if (buflen <= fixed - buffer) { /* watch out for wrap-around */
- errno = ERANGE;
- return (NULL);
- }
-
- buflen -= fixed - buffer;
-
- buffer = fixed;
-
-#ifdef _LP64
- /*
- * this is just a rationality check; we need to make
- * sure that there's enough space for the gr_mem array
- * as well... easiest place to do that is when we copy
- * them in place.
- */
-
- if (sptr->nsc_ret.nsc_bufferbytesused +
- /*
- * ^^^ number of bytes from nscd
- */
- (sizeof (char **)) +
- /*
- * ^^^ we need 8 bytes for gr_mem
- */
- (sizeof (char *) - 1) -
- /*
- * ^^^ plus space for pssibly fixing aligment of gr_mem
- */
- sizeof (group32_t)
- /*
- * ^^^ because we don't put this in the usr buffer
- */
- > buflen) {
-#else
- if (sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct group)
- > buflen) {
-#endif /* _LP64 */
- errno = ERANGE;
- return (NULL);
- }
-
- if (sptr->nsc_ret.nsc_return_code != SUCCESS)
- return (NULL);
-
-/*
- * ncsd is a 32bit application, so use 32bit data items if we are in 64bit mode
- */
-#ifdef _LP64
-
- (void) memcpy(buffer,
- (sptr->nsc_ret.nsc_u.buff + sizeof (group32_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (group32_t)));
-
- group64.gr_name = (char *)(sptr->nsc_ret.nsc_u.grp.gr_name +
- (uintptr_t)buffer);
- group64.gr_passwd = (char *)(sptr->nsc_ret.nsc_u.grp.gr_passwd +
- (uintptr_t)buffer);
- group64.gr_gid = sptr->nsc_ret.nsc_u.grp.gr_gid;
-
- group64.gr_mem = (char **)((uintptr_t)buffer +
- sptr->nsc_ret.nsc_bufferbytesused - sizeof (group32_t));
- group64.gr_mem = (char **)(((uintptr_t)group64.gr_mem + 7) & ~7);
-
- gr_mem32 = (char **)(uintptr_t)sptr->nsc_ret.nsc_u.grp.gr_mem;
- buffer32 = buffer;
-
- for (i = 0; ; i++) {
- index = *((uptr32_t *)
- ((uintptr_t)gr_mem32 + (uintptr_t)buffer32));
-
- /*
- * make sure there's enough space to copy the pointer...
- */
- if (&group64.gr_mem[i + 1] >
- (char **)((uintptr_t)buffer + buflen)) {
- errno = ERANGE;
- return (NULL);
- }
-
- if (index == 0)
- break;
-
- group64.gr_mem[i] = (char *)(index + buffer);
- buffer32 += sizeof (uptr32_t);
-
- }
- group64.gr_mem[i] = NULL;
-
- *result = group64;
-#else
-
- (void) memcpy(buffer,
- (sptr->nsc_ret.nsc_u.buff + sizeof (struct group)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct group)));
-
- sptr->nsc_ret.nsc_u.grp.gr_name += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.grp.gr_passwd += (uintptr_t)buffer;
-
- sptr->nsc_ret.nsc_u.grp.gr_mem =
- (char **)((uintptr_t)sptr->nsc_ret.nsc_u.grp.gr_mem +
- (uintptr_t)buffer);
-
- i = 0;
- while (sptr->nsc_ret.nsc_u.grp.gr_mem[i]) {
- sptr->nsc_ret.nsc_u.grp.gr_mem[i] += (uintptr_t)buffer;
- i++;
- }
-
- *result = sptr->nsc_ret.nsc_u.grp;
-
-#endif /* _LP64 */
+ nss_XbyY_args_t arg;
- return (result);
+ NSS_XbyY_INIT(&arg, result, buffer, buflen, str2group);
+ arg.key.gid = gid;
+ (void) nss_search(&db_root, _nss_initf_group,
+ NSS_DBOP_GROUP_BYGID, &arg);
+ return ((struct group *)NSS_XbyY_FINI(&arg));
}
struct group *
@@ -452,6 +239,12 @@ fgetgrent_r(FILE *f, struct group *result, char *buffer, int buflen)
* number of valid gids in gid_array (may be zero)
* or
* -1 (and errno set appropriately) on errors (none currently defined)
+ *
+ * NSS2 Consistency enhancements:
+ * The "files normal" format between an application and nscd for the
+ * NSS_DBOP_GROUP_BYMEMBER nss_search operation is defined to be a
+ * processed array of numgids [up to maxgids] gid_t values. gid_t
+ * values in the array are unique.
*/
static nss_status_t process_cstr(const char *, int, struct nss_groupsbymem *);
@@ -468,6 +261,10 @@ _getgroupsbymember(const char *username, gid_t gid_array[],
arg.gid_array = gid_array;
arg.maxgids = maxgids;
arg.numgids = numgids;
+ /*
+ * In backwards compatibility mode, use the old str2group &
+ * process_cstr interfaces. Ditto within nscd processing.
+ */
arg.str2ent = str2group;
arg.process_cstr = process_cstr;
@@ -505,14 +302,6 @@ _getgroupsbymember(const char *username, gid_t gid_array[],
(void) nss_search(&db_root, _nss_initf_group,
NSS_DBOP_GROUP_BYMEMBER, &arg);
-#ifdef undef
- /*
- * Only do this if there's existing code somewhere that relies on
- * initgroups() doing an endgrent() -- most unlikely.
- */
- endgrent();
-#endif /* undef */
-
return (arg.numgids);
}
@@ -560,8 +349,15 @@ str2group(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
* We copy the input string into the output buffer and
* operate on it in place.
*/
- (void) memcpy(buffer, instr, lenstr);
- buffer[lenstr] = '\0';
+ if (instr != buffer) {
+ /* Overlapping buffer copies are OK */
+ (void) memmove(buffer, instr, lenstr);
+ buffer[lenstr] = '\0';
+ }
+
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
next = buffer;
diff --git a/usr/src/lib/libc/port/gen/getnetgrent.c b/usr/src/lib/libc/port/gen/getnetgrent.c
index cae4720b81..d8d111e818 100644
--- a/usr/src/lib/libc/port/gen/getnetgrent.c
+++ b/usr/src/lib/libc/port/gen/getnetgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -74,10 +73,14 @@ _nss_initf_netgroup(p)
* - getnetgrent(...) is repeatedly invoked by the user to extract the
* contents of the entry found by setnetgrent().
* - endnetgrent() is almost like a real endXXXent routine.
- * If we were certain that all the backends could provide netgroup information
- * in a common form, we could make the setnetgrent() backend return the entire
- * entry to the frontend, then implement getnetgrent() and endnetgrent()
- * strictly in the frontend (aka here). But we're not certain, so we won't.
+ * The behaviour in NSS was:
+ * If we were certain that all the backends could provide netgroup information
+ * in a common form, we could make the setnetgrent() backend return the entire
+ * entry to the frontend, then implement getnetgrent() and endnetgrent()
+ * strictly in the frontend (aka here). But we're not certain, so we won't.
+ * In NSS2:
+ * Since nscd returns the results, and it is nscd that accumulates
+ * the results, then we can return the entire result on the setnetgrent.
*
* NOTE:
* In the SunOS 4.x (YP) version of this code, innetgr() did not
diff --git a/usr/src/lib/libc/port/gen/getpwnam.c b/usr/src/lib/libc/port/gen/getpwnam.c
index 1d0aad906a..7a3b8c4b37 100644
--- a/usr/src/lib/libc/port/gen/getpwnam.c
+++ b/usr/src/lib/libc/port/gen/getpwnam.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
diff --git a/usr/src/lib/libc/port/gen/getpwnam_r.c b/usr/src/lib/libc/port/gen/getpwnam_r.c
index f318f1aec0..75b8fa171d 100644
--- a/usr/src/lib/libc/port/gen/getpwnam_r.c
+++ b/usr/src/lib/libc/port/gen/getpwnam_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -67,86 +66,6 @@ struct passwd *
_uncached_getpwnam_r(const char *name, struct passwd *result, char *buffer,
int buflen);
-static struct passwd *
-process_getpw(struct passwd *result, char *buffer, int buflen,
- nsc_data_t *sptr, int ndata);
-
-/* ARGSUSED4 */
-static struct passwd *
-process_getpw(struct passwd *result, char *buffer, int buflen,
- nsc_data_t *sptr, int ndata)
-{
-
- char *fixed;
-#ifdef _LP64
- struct passwd pass64;
-#endif
-
-#ifdef _LP64
- fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
-#else
- fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
-#endif
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (sptr->nsc_ret.nsc_return_code != SUCCESS)
- return (NULL);
-
-#ifdef _LP64
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (passwd32_t)
- > buflen) {
-#else
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (struct passwd)
- > buflen) {
-#endif
- errno = ERANGE;
- return (NULL);
- }
-
-#ifdef _LP64
-
- (void) memcpy(buffer,
- (sptr->nsc_ret.nsc_u.buff + sizeof (passwd32_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (passwd32_t)));
-
- pass64.pw_name = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_name +
- (uintptr_t)buffer);
- pass64.pw_passwd = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_passwd +
- (uintptr_t)buffer);
- pass64.pw_uid = sptr->nsc_ret.nsc_u.pwd.pw_uid;
- pass64.pw_gid = sptr->nsc_ret.nsc_u.pwd.pw_gid;
- pass64.pw_age = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_age +
- (uintptr_t)buffer);
- pass64.pw_comment = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_comment +
- (uintptr_t)buffer);
- pass64.pw_gecos = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_gecos +
- (uintptr_t)buffer);
- pass64.pw_dir = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_dir +
- (uintptr_t)buffer);
- pass64.pw_shell = (char *)(sptr->nsc_ret.nsc_u.pwd.pw_shell +
- (uintptr_t)buffer);
-
- *result = pass64;
-#else
- sptr->nsc_ret.nsc_u.pwd.pw_name += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_passwd += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_age += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_comment += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_gecos += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_dir += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.pwd.pw_shell += (uintptr_t)buffer;
-
- *result = sptr->nsc_ret.nsc_u.pwd;
-
- (void) memcpy(buffer,
- (sptr->nsc_ret.nsc_u.buff + sizeof (struct passwd)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct passwd)));
-#endif
-
- return (result);
-}
-
/*
* POSIX.1c Draft-6 version of the function getpwnam_r.
* It was implemented by Solaris 2.3.
@@ -154,48 +73,17 @@ process_getpw(struct passwd *result, char *buffer, int buflen,
struct passwd *
_getpwnam_r(const char *name, struct passwd *result, char *buffer, int buflen)
{
- /*
- * allocate data on the stack for passwd information
- */
- union {
- nsc_data_t s_d;
- char s_b[1024];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct passwd *resptr = NULL;
-
- if ((name == (const char *)NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
+ nss_XbyY_args_t arg;
+
+ if (name == (const char *)NULL) {
errno = ERANGE;
- return ((struct passwd *)NULL);
- }
- ndata = sizeof (space);
- adata = strlen(name) + sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETPWNAM;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
return (NULL);
- default:
- return ((struct passwd *)_uncached_getpwnam_r(name, result,
- buffer, buflen));
}
- resptr = process_getpw(result, buffer, buflen, sptr, ndata);
-
- /*
- * check if doors reallocated the memory underneath us
- * if they did munmap it or suffer a memory leak
- */
- if (sptr != &space.s_d)
- munmap((void *)sptr, ndata);
-
- return (resptr);
+ NSS_XbyY_INIT(&arg, result, buffer, buflen, str2passwd);
+ arg.key.name = name;
+ (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYNAME,
+ &arg);
+ return ((struct passwd *)NSS_XbyY_FINI(&arg));
}
/*
@@ -205,40 +93,13 @@ _getpwnam_r(const char *name, struct passwd *result, char *buffer, int buflen)
struct passwd *
_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, int buflen)
{
- union {
- nsc_data_t s_d;
- char s_b[1024];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct passwd *resptr = NULL;
-
- ndata = sizeof (space);
- adata = sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETPWUID;
- space.s_d.nsc_call.nsc_u.uid = uid;
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- return (NULL);
- default:
- return ((struct passwd *)_uncached_getpwuid_r(uid, result,
- buffer, buflen));
- }
- resptr = process_getpw(result, buffer, buflen, sptr, ndata);
-
- /*
- * check if doors reallocated the memory underneath us
- * if they did munmap it or suffer a memory leak
- */
- if (sptr != &space.s_d)
- munmap((void *)sptr, ndata);
+ nss_XbyY_args_t arg;
- return (resptr);
+ NSS_XbyY_INIT(&arg, result, buffer, buflen, str2passwd);
+ arg.key.uid = uid;
+ (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYUID,
+ &arg);
+ return ((struct passwd *)NSS_XbyY_FINI(&arg));
}
@@ -397,8 +258,15 @@ str2passwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
* We copy the input string into the output buffer and
* operate on it in place.
*/
- (void) memcpy(buffer, instr, lenstr);
- buffer[lenstr] = '\0';
+ if (instr != buffer) {
+ /* Overlapping buffer copies are OK */
+ (void) memmove(buffer, instr, lenstr);
+ buffer[lenstr] = '\0';
+ }
+
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
next = buffer;
diff --git a/usr/src/lib/libc/port/gen/getspent_r.c b/usr/src/lib/libc/port/gen/getspent_r.c
index 565ede148e..78c42b7b62 100644
--- a/usr/src/lib/libc/port/gen/getspent_r.c
+++ b/usr/src/lib/libc/port/gen/getspent_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,7 +47,7 @@ int str2spwd(const char *, int, void *,
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
-static void
+void
_nss_initf_shadow(nss_db_params_t *p)
{
p->name = NSS_DBNAM_SHADOW;
@@ -204,8 +203,16 @@ str2spwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
if (lencopy + 1 > buflen) {
return (NSS_STR_PARSE_ERANGE);
}
- (void) memcpy(buffer, instr, lencopy);
- buffer[lencopy] = 0;
+
+ if (instr != buffer) {
+ /* Overlapping buffer copies are OK */
+ (void) memmove(buffer, instr, lencopy);
+ buffer[lencopy] = 0;
+ }
+
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
black_magic = (*instr == '+' || *instr == '-');
shadow->sp_namp = bufp = buffer;
diff --git a/usr/src/lib/libc/port/gen/getxby_door.c b/usr/src/lib/libc/port/gen/getxby_door.c
index d4e64868e1..e659ed9dcb 100644
--- a/usr/src/lib/libc/port/gen/getxby_door.c
+++ b/usr/src/lib/libc/port/gen/getxby_door.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,18 +29,32 @@
#include "synonyms.h"
#include <mtlib.h>
#include <sys/types.h>
+#include <errno.h>
#include <pwd.h>
#include <nss_dbdefs.h>
#include <stdio.h>
+#include <string.h>
#include <synch.h>
#include <sys/param.h>
#include <fcntl.h>
#include <unistd.h>
+#include <stdlib.h>
#include <getxby_door.h>
#include <sys/door.h>
+#include <procfs.h>
+#include <door.h>
#include "libc.h"
+#include "tsd.h"
#include "base_conversion.h"
+/* nss<->door hints */
+static mutex_t hints_lock = DEFAULTMUTEX;
+static size_t door_bsize = 0;
+static size_t door_nbsize = 0;
+static int proc_is_cache = -1;
+
+/* library<->nscd door interaction apis */
+
/*
*
* Routine that actually performs the door call.
@@ -65,7 +78,7 @@
* and we're a multi-threaded application. Note that we cannot protect
* the application if it closes the fd and it is multi-threaded.
*
- * int _nsc_trydoorcall(void *dptr, int *bufsize, int *actualsize);
+ * int _nsc_trydoorcall(void *dptr, size_t *bufsize, size_t *actualsize);
*
* *dptr IN: points to arg buffer OUT: points to results buffer
* *bufsize IN: overall size of buffer OUT: overall size of buffer
@@ -80,36 +93,166 @@
*
*/
-static mutex_t _door_lock = DEFAULTMUTEX;
+/*
+ * Max size for list of db names supported by the private nscd
+ * No implied max here, any size will do, fixed size chosen to
+ * reduce yet another malloc
+ */
-int
-_nsc_trydoorcall(nsc_data_t **dptr, int *ndata, int *adata)
+#define BD_BUFSIZE 1024
+#define BD_SEP ','
+
+typedef struct _nsc_door_t {
+ int doorfd;
+ mutex_t door_lock;
+ door_info_t doori;
+} nsc_door_t;
+
+static nsc_door_t nsc_door[2] = {
+ { -1, DEFAULTMUTEX, { 0 } }, /* front (fattached) door */
+ { -1, DEFAULTMUTEX, { 0 } }, /* back (private) door */
+};
+
+/* assumed to be locked by using nsc_door[1] mutex */
+static char *nsc_db_buf = NULL;
+static char **nsc_db_list = NULL;
+
+/*
+ * Check for a valid and matching db in the list.
+ * assume list is in the locked state.
+ */
+
+static int
+_nsc_use_backdoor(char *db)
+{
+ char **ndb;
+
+ if (db && nsc_db_buf != NULL && nsc_db_list != NULL) {
+ for (ndb = nsc_db_list; *ndb; ndb++) {
+ if (strcmp(db, *ndb) == 0)
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * flush private db lists
+ */
+static void
+_nsc_flush_private_db()
+{
+ if (nsc_db_buf != NULL) {
+ libc_free((void *)nsc_db_buf);
+ nsc_db_buf = NULL;
+ }
+ if (nsc_db_list != NULL) {
+ libc_free((void *)nsc_db_list);
+ nsc_db_list = NULL;
+ }
+}
+
+/*
+ * init/update nsc_db_buf given buff containing list of
+ * db's to be processed by a private nscd.
+ * This function assumes it has a well formed string from nscd.
+ */
+
+static int
+_nsc_init_private_db(char *dblist)
+{
+ char *cp, **lp;
+ int buflen = 0;
+ int arrlen = 0;
+
+ if (dblist == NULL)
+ return (0);
+
+ /* reset db list */
+ _nsc_flush_private_db();
+
+ /* rebuild fresh list */
+ buflen = strlen(dblist) + 1;
+ for (cp = dblist; *cp; cp++)
+ if (*cp == BD_SEP)
+ arrlen++;
+ if (cp == dblist)
+ return (0);
+ arrlen += 2;
+ nsc_db_buf = (char *)libc_malloc(buflen);
+ if (nsc_db_buf == (char *)NULL)
+ return (0);
+ nsc_db_list = (char **)libc_malloc(arrlen * sizeof (char *));
+ if (nsc_db_list == (char **)NULL) {
+ libc_free((void *)nsc_db_buf);
+ nsc_db_buf = NULL;
+ return (0);
+ }
+ (void) memcpy(nsc_db_buf, dblist, buflen);
+ lp = nsc_db_list;
+ *lp++ = nsc_db_buf;
+ for (cp = nsc_db_buf; *cp; ) {
+ if (*cp == BD_SEP) {
+ *cp++ = '\0';
+ *lp++ = cp;
+ } else
+ cp++;
+ }
+ *lp = NULL;
+ return (1);
+}
+
+/*
+ * _nsc_initdoor_fp attempts to validate the given door and
+ * confirm that it is still available for use. The options are:
+ * Front door:
+ * If it's not open, attempt to open or error
+ * If it's open attempt to validate.
+ * If it's not validatable, reset fd and try again.
+ * Other wise it open and validated, return success
+ * Per user (back) door:
+ * This door is passed to the client through th front door
+ * attempt to validate it. If it can't be validated, it
+ * must be reset. Then send a NSS_ALTRESET error, so nscd can
+ * forward another fd if desired.
+ */
+
+static nss_status_t
+_nsc_initdoor_fp(nsc_door_t *dp)
{
- static int doorfd = -1;
- static door_info_t real_door;
+
door_info_t my_door;
- door_arg_t param;
+
+ if (dp == NULL) {
+ errno = ENOTCONN;
+ return (NSS_ERROR);
+ }
/*
- * the first time in we try and open and validate the door.
- * the validations are that the door must have been
- * created with the name service door cookie and
- * that the file attached to the door is owned by root
- * and readonly by user, group and other. If any of these
- * validations fail we refuse to use the door.
+ * the first time in we try and open and validate the front door.
+ * A front door request may return an alternate private back door
+ * that the client should use instead.
+ *
+ * To validate a door the door must have been created with
+ * the name service door cookie. The front door is file
+ * attached, owned by root and readonly by user, group and
+ * other. If any of these validations fail we refuse to use
+ * the door. A back door is delivered from the front door
+ * via a door_desc_t, and have the same cooke notification.
*/
- lmutex_lock(&_door_lock);
+ lmutex_lock(&dp->door_lock);
try_again:
- if (doorfd == -1) {
+ if (dp->doorfd == -1 && dp == &nsc_door[0]) { /* open front door */
int tbc[3];
int i;
- if ((doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0)) == -1) {
- lmutex_unlock(&_door_lock);
- return (NOSERVER);
+ dp->doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0);
+ if (dp->doorfd == -1) {
+ lmutex_unlock(&dp->door_lock);
+ return (NSS_ERROR);
}
/*
@@ -118,14 +261,14 @@ try_again:
*/
i = 0;
- while (doorfd < 3) { /* we have a reserved fd */
- tbc[i++] = doorfd;
- if ((doorfd = dup(doorfd)) < 0) {
+ while (dp->doorfd < 3) { /* we have a reserved fd */
+ tbc[i++] = dp->doorfd;
+ if ((dp->doorfd = dup(dp->doorfd)) < 0) {
while (i--)
(void) close(tbc[i]);
- doorfd = -1;
- lmutex_unlock(&_door_lock);
- return (NOSERVER);
+ dp->doorfd = -1;
+ lmutex_unlock(&dp->door_lock);
+ return (NSS_ERROR);
}
}
@@ -135,38 +278,76 @@ try_again:
/*
* mark this door descriptor as close on exec
*/
- (void) fcntl(doorfd, F_SETFD, FD_CLOEXEC);
- if (__door_info(doorfd, &real_door) == -1 ||
- (real_door.di_attributes & DOOR_REVOKED) ||
- real_door.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {
+ (void) fcntl(dp->doorfd, F_SETFD, FD_CLOEXEC);
+ if (__door_info(dp->doorfd, &dp->doori) < 0 ||
+ (dp->doori.di_attributes & DOOR_REVOKED) ||
+ dp->doori.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {
/*
* we should close doorfd because we just opened it
*/
- (void) close(doorfd);
- doorfd = -1;
- lmutex_unlock(&_door_lock);
- return (NOSERVER);
+ (void) close(dp->doorfd);
+ dp->doorfd = -1;
+ (void) memset((void *)&dp->doori,
+ '\0', sizeof (door_info_t));
+ lmutex_unlock(&dp->door_lock);
+ errno = ECONNREFUSED;
+ return (NSS_ERROR);
}
} else {
- if (__door_info(doorfd, &my_door) == -1 ||
+ if (__door_info(dp->doorfd, &my_door) < 0 ||
my_door.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE ||
- my_door.di_uniquifier != real_door.di_uniquifier) {
+ my_door.di_uniquifier != dp->doori.di_uniquifier) {
/*
* don't close it -
* someone else has clobbered fd
*/
- doorfd = -1;
+ dp->doorfd = -1;
+ (void) memset((void *)&dp->doori,
+ '\0', sizeof (door_info_t));
+ if (dp == &nsc_door[1]) { /* reset back door */
+ /* flush invalid db list */
+ _nsc_flush_private_db();
+ lmutex_unlock(&dp->door_lock);
+ return (NSS_ALTRESET);
+ }
goto try_again;
}
if (my_door.di_attributes & DOOR_REVOKED) {
- (void) close(doorfd); /* nscd exited .... */
- doorfd = -1; /* try and restart connection */
+ (void) close(dp->doorfd); /* nscd exited .... */
+ dp->doorfd = -1; /* try and restart connection */
+ (void) memset((void *)&dp->doori,
+ '\0', sizeof (door_info_t));
+ if (dp == &nsc_door[1]) { /* back door reset */
+ /* flush invalid db list */
+ _nsc_flush_private_db();
+ lmutex_unlock(&dp->door_lock);
+ return (NSS_ALTRESET);
+ }
goto try_again;
}
}
- lmutex_unlock(&_door_lock);
+ lmutex_unlock(&dp->door_lock);
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Try the door request once only, to the specified connection.
+ * return the results or error.
+ */
+
+static nss_status_t
+_nsc_try1door(nsc_door_t *dp, void **dptr, size_t *ndata,
+ size_t *adata, int *pdesc)
+{
+ door_arg_t param;
+ int ret;
+ nss_pheader_t *rp;
+
+ ret = _nsc_initdoor_fp(dp);
+ if (ret != NSS_SUCCESS)
+ return (ret);
param.rbuf = (char *)*dptr;
param.rsize = *ndata;
@@ -174,15 +355,346 @@ try_again:
param.data_size = *adata;
param.desc_ptr = NULL;
param.desc_num = 0;
- if (__door_call(doorfd, &param) == -1) {
- return (NOSERVER);
+ ret = __door_call(dp->doorfd, &param);
+ if (ret < 0) {
+ return (NSS_ERROR);
+ }
+ *adata = param.data_size;
+ *ndata = param.rsize;
+ *dptr = (void *)param.data_ptr;
+ rp = (nss_pheader_t *)((void *)param.rbuf);
+ if (pdesc != NULL && rp && rp->p_status == NSS_ALTRETRY &&
+ param.desc_ptr != NULL && param.desc_num > 0) {
+ if ((param.desc_ptr->d_attributes & DOOR_DESCRIPTOR) &&
+ param.desc_ptr->d_data.d_desc.d_descriptor >= 0 &&
+ param.desc_ptr->d_data.d_desc.d_id != 0) {
+ /* have an alt descriptor */
+ *pdesc = param.desc_ptr->d_data.d_desc.d_descriptor;
+ /* got a NSS_ALTRETRY command */
+ return (NSS_ALTRETRY);
+ }
+ errno = EINVAL;
+ return (NSS_ERROR); /* other error? */
}
- *adata = (int)param.data_size;
- *ndata = (int)param.rsize;
- *dptr = (nsc_data_t *)(uintptr_t)param.data_ptr;
if (*adata == 0 || *dptr == NULL) {
- return (NOSERVER);
+ errno = ENOTCONN;
+ return (NSS_ERROR);
}
- return ((*dptr)->nsc_ret.nsc_return_code);
+ if (rp->p_status == NSS_ALTRESET ||
+ rp->p_status == NSS_ALTRETRY ||
+ rp->p_status == NSS_TRYLOCAL)
+ return (rp->p_status);
+
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Backwards compatible API
+ */
+
+nss_status_t
+_nsc_trydoorcall(void **dptr, size_t *ndata, size_t *adata)
+{
+ return (_nsc_try1door(&nsc_door[0], dptr, ndata, adata, NULL));
+}
+
+/*
+ * Send the request to the designated door, based on the supplied db
+ * Retry on the alternate door fd if possible.
+ */
+
+nss_status_t
+_nsc_trydoorcall_ext(void **dptr, size_t *ndata, size_t *adata)
+{
+ int ret = NSS_ALTRETRY;
+ nsc_door_t *frontd = &nsc_door[0];
+ nsc_door_t *backd = &nsc_door[1];
+ int fd;
+
+ nss_pheader_t *ph, ph_save;
+ char *dbl;
+ char *db = NULL;
+ nss_dbd_t *dbd;
+ int fb2frontd = 0;
+ int reset_frontd = 0;
+
+ ph = (nss_pheader_t *)*dptr;
+ dbd = (nss_dbd_t *)((void *)((char *)ph + ph->dbd_off));
+ if (dbd->o_name != 0)
+ db = (char *)dbd + dbd->o_name;
+ ph_save = *ph;
+
+ while (ret == NSS_ALTRETRY || ret == NSS_ALTRESET) {
+ /* try private (back) door first if it exists and applies */
+ if (db != NULL && backd->doorfd > 0 && fb2frontd == 0 &&
+ _nsc_use_backdoor(db)) {
+ ret = _nsc_try1door(backd, dptr, ndata, adata, NULL);
+ if (ret == NSS_ALTRESET) {
+ /*
+ * received NSS_ALTRESET command,
+ * retry on front door
+ */
+ lmutex_lock(&backd->door_lock);
+ backd->doorfd = -1;
+ (void) memset((void *)&backd->doori,
+ '\0', sizeof (door_info_t));
+ /* flush now invalid db list */
+ _nsc_flush_private_db();
+ lmutex_unlock(&backd->door_lock);
+ continue;
+ } else if (ret == NSS_ALTRETRY) {
+ /*
+ * received NSS_ALTRETRY command,
+ * fall back and retry on front door
+ */
+ fb2frontd = 1;
+ *ph = ph_save;
+ /*
+ * tell the front door server, this is
+ * a fallback call
+ */
+ ph->p_status = NSS_ALTRETRY;
+ continue;
+ }
+
+ /* return the result or error */
+ break;
+ }
+
+ /* try the front door */
+ fd = -1;
+ ret = _nsc_try1door(frontd, dptr, ndata, adata, &fd);
+
+ if (ret != NSS_ALTRETRY) {
+ /*
+ * got a success or failure result.
+ * but front door should never send NSS_ALTRESET
+ */
+ if (ret == NSS_ALTRESET)
+ /* reset the front door */
+ reset_frontd = 1;
+ else
+ /*
+ * not NSS_ALTRETRY and not NSS_ALTRESET
+ * return the result or error
+ */
+ break;
+ } else if (fb2frontd == 1) {
+ /*
+ * front door should never send NSS_ALTRETRY
+ * in a fallback call. Reset the front door.
+ */
+ reset_frontd = 1;
+ }
+
+ if (reset_frontd == 1) {
+ lmutex_lock(&frontd->door_lock);
+ frontd->doorfd = -1;
+ (void) memset((void *)&frontd->doori,
+ '\0', sizeof (door_info_t));
+ lmutex_unlock(&frontd->door_lock);
+ /* error out */
+ ret = NSS_ERROR;
+ break;
+ }
+
+ /* process NSS_ALTRETRY request from front door */
+ if (fd < 0)
+ continue; /* no new door given, try again */
+
+ /* update and try alternate door */
+ lmutex_lock(&backd->door_lock);
+ if (backd->doorfd >= 0) {
+ /* unexpected open alt door - clean up, continue */
+ _nsc_flush_private_db();
+ (void) close(backd->doorfd);
+ }
+
+ /* set up back door fd */
+ backd->doorfd = fd;
+
+ /* set up back door db list */
+ ph = (nss_pheader_t *)*dptr;
+ dbl = ((char *)ph) + ph->data_off;
+
+ if (_nsc_init_private_db(dbl) == 0) {
+ /* could not init db list, try again */
+ (void) close(backd->doorfd);
+ backd->doorfd = -1;
+ lmutex_unlock(&backd->door_lock);
+ continue;
+ }
+ if (door_info(backd->doorfd, &backd->doori) < 0 ||
+ (backd->doori.di_attributes & DOOR_REVOKED) ||
+ backd->doori.di_data !=
+ (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {
+ /* doorfd bad, or must not really be open */
+ (void) close(backd->doorfd);
+ backd->doorfd = -1;
+ (void) memset((void *)&backd->doori,
+ '\0', sizeof (door_info_t));
+ }
+ (void) fcntl(backd->doorfd, F_SETFD, FD_CLOEXEC);
+ lmutex_unlock(&backd->door_lock);
+ /* NSS_ALTRETRY new back door */
+ *ph = ph_save;
+ }
+ return (ret);
+}
+
+/*
+ * Get the current (but growable) buffer size for a NSS2 packet.
+ * Heuristic algorithm used:
+ * 1) Make sure it's at least NSS_BUFLEN_DOOR in length (16k default)
+ * 2) if an incoming user buffer is > larger than the current size
+ * Make the buffer at least NSS_BUFLEN_DOOR/2+user buffer size
+ * This should account for any reasonable nss_pheader, keys
+ * extended area etc.
+ * 3) keep the prototype/debugging (private)NSS_BUFLEN option
+ * to change any preconfigured value if needed(?)
+ */
+
+static size_t
+_nsc_getdoorbsize(size_t min_size)
+{
+ if (!door_bsize) {
+ lmutex_lock(&hints_lock);
+ if (!door_bsize) {
+ /* future work - get nscd hint & use hint size */
+ door_bsize = ROUND_UP(door_bsize, NSS_BUFSIZ);
+ if (door_bsize < NSS_BUFLEN_DOOR) {
+ door_bsize = NSS_BUFLEN_DOOR;
+ }
+ }
+ lmutex_unlock(&hints_lock);
+ }
+ if (min_size && door_bsize < (min_size + NSS_BUFLEN_DOOR/2)) {
+ lmutex_lock(&hints_lock);
+ if (door_bsize < (min_size + NSS_BUFLEN_DOOR/2)) {
+ min_size += NSS_BUFLEN_DOOR;
+ door_bsize = ROUND_UP(min_size, NSS_BUFSIZ);
+ }
+ lmutex_unlock(&hints_lock);
+ }
+ return (door_bsize);
+}
+
+static void
+_nsc_freedbuf(void *arg)
+{
+ nss_XbyY_buf_t *tsdbuf = arg;
+
+ if (tsdbuf != NULL && tsdbuf->buffer != NULL) {
+ lfree(tsdbuf->buffer, (size_t)tsdbuf->buflen);
+ tsdbuf->result = NULL;
+ tsdbuf->buffer = NULL;
+ tsdbuf->buflen = 0;
+ }
+}
+
+/*
+ * _nsc_getdoorbuf - return the client side per thread door buffer
+ * Elsewhere, it is assumed that the header is 0'd upon return from here.
+ */
+
+int
+_nsc_getdoorbuf(void **doorptr, size_t *bufsize)
+{
+ nss_XbyY_buf_t *tsdbuf;
+ char *bp;
+ size_t dsize;
+
+ if (doorptr == NULL || bufsize == NULL)
+ return (-1);
+
+ /* Get thread specific pointer to door buffer */
+ tsdbuf = tsdalloc(_T_DOORBUF, sizeof (nss_XbyY_buf_t), _nsc_freedbuf);
+ if (tsdbuf == NULL)
+ return (-1);
+
+ /* if door buffer does not exist create it */
+ if (tsdbuf->buffer == NULL) {
+ dsize = _nsc_getdoorbsize(*bufsize);
+
+ /* setup a door buffer with a total length of dsize */
+ bp = lmalloc(dsize);
+ if (bp == NULL)
+ return (-1);
+ tsdbuf->buffer = bp;
+ tsdbuf->buflen = dsize;
+ } else {
+ /* check old buffer size and resize if needed */
+ if (*bufsize) {
+ dsize = _nsc_getdoorbsize(*bufsize);
+ if (tsdbuf->buflen < dsize) {
+ lfree(tsdbuf->buffer, (size_t)tsdbuf->buflen);
+ bp = lmalloc(dsize);
+ if (bp == NULL)
+ return (-1);
+ tsdbuf->buffer = bp;
+ tsdbuf->buflen = dsize;
+ }
+ }
+ /* freshly malloc'd door bufs are 0'd */
+ /* 0 header for now. Zero entire buf(?) TDB */
+ (void) memset((void *)tsdbuf->buffer, 0,
+ (size_t)sizeof (nss_pheader_t));
+
+ }
+ *doorptr = (void *)tsdbuf->buffer;
+ *bufsize = tsdbuf->buflen;
+ return (0);
+}
+
+void
+_nsc_resizedoorbuf(size_t bsize)
+{
+ /* signal to update if new door size is desired */
+ lmutex_lock(&hints_lock);
+ if (bsize > door_bsize && door_nbsize < bsize)
+ door_nbsize = bsize;
+ lmutex_unlock(&hints_lock);
+}
+
+/*
+ * Check uid and /proc/PID/psinfo to see if this process is nscd
+ * If it is set the appropriate flags and allow policy reconfiguration.
+ */
+int
+_nsc_proc_is_cache()
+{
+ psinfo_t pinfo;
+ char fname[128];
+ int ret;
+ int fd;
+
+ if (proc_is_cache >= 0)
+ return (proc_is_cache);
+ lmutex_lock(&hints_lock);
+ if (proc_is_cache >= 0) {
+ lmutex_unlock(&hints_lock);
+ return (proc_is_cache);
+ }
+ proc_is_cache = 0;
+ /* It can't be nscd if it's not running as root... */
+ if (getuid() != 0) {
+ lmutex_unlock(&hints_lock);
+ return (0);
+ }
+ ret = snprintf(fname, 128, "/proc/%d/psinfo", getpid());
+ if (ret > 0 && ret < 128) {
+ if ((fd = open(fname, O_RDONLY)) > 0) {
+ ret = read(fd, &pinfo, sizeof (psinfo_t));
+ (void) close(fd);
+ if (ret == sizeof (psinfo_t) &&
+ (strcmp(pinfo.pr_fname, "nscd") == 0)) {
+ /* process runs as root and is named nscd */
+ /* that's good enough for now */
+ proc_is_cache = 1;
+ }
+ }
+ }
+ lmutex_unlock(&hints_lock);
+ return (proc_is_cache);
}
diff --git a/usr/src/lib/libc/port/gen/getxby_door.h b/usr/src/lib/libc/port/gen/getxby_door.h
index fd4c6db044..54741d08b5 100644
--- a/usr/src/lib/libc/port/gen/getxby_door.h
+++ b/usr/src/lib/libc/port/gen/getxby_door.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1994, 1999-2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,283 +45,31 @@ extern "C" {
#include <exec_attr.h>
#include <prof_attr.h>
#include <user_attr.h>
-
-#ifdef _LP64
-
-/* NB uid_t and gid_t are the same size in 32 & 64 bit mode */
-
-typedef unsigned int uptr32_t; /* 32bit pointer type */
-
-typedef struct passwd32 {
- uptr32_t pw_name;
- uptr32_t pw_passwd;
- uid_t pw_uid;
- gid_t pw_gid;
- uptr32_t pw_age;
- uptr32_t pw_comment;
- uptr32_t pw_gecos;
- uptr32_t pw_dir;
- uptr32_t pw_shell;
-} passwd32_t;
-
-typedef struct group32 {
- uptr32_t gr_name;
- uptr32_t gr_passwd;
- gid_t gr_gid;
- uptr32_t gr_mem;
-} group32_t;
-
-/* NB int is the same size in 32 & 64 bit mode */
-
-typedef struct hostent32 {
- uptr32_t h_name; /* official name of host */
- uptr32_t h_aliases; /* alias list */
- int h_addrtype; /* host address type */
- int h_length; /* length of address */
- uptr32_t h_addr_list; /* list of addresses from name server */
-#define h_addr h_addr_list[0] /* address, for backward compatiblity */
-} hostent32_t;
-
-typedef struct execstr32_s {
- uptr32_t name;
- uptr32_t policy;
- uptr32_t type;
- uptr32_t res1;
- uptr32_t res2;
- uptr32_t id;
- uptr32_t attr;
-} execstr32_t;
-
-typedef struct profstr32_s {
- uptr32_t name;
- uptr32_t res1;
- uptr32_t res2;
- uptr32_t desc;
- uptr32_t attr;
-} profstr32_t;
-
-typedef struct userstr32_s {
- uptr32_t name;
- uptr32_t qualifier;
- uptr32_t res1;
- uptr32_t res2;
- uptr32_t attr;
-} userstr32_t;
-
-#endif /* _LP64 */
-
-/*
- * statistics & control structure
- */
-
-typedef struct nsc_stat {
- int nsc_pos_cache_hits; /* hits on real entries */
- int nsc_neg_cache_hits; /* hits on hegative entries */
- int nsc_pos_cache_misses; /* miss that results in real entry */
- int nsc_neg_cache_misses; /* miss that results in neg entry */
- int nsc_entries; /* count of cache entries */
- int nsc_throttle_count; /* count of load shedding */
- int nsc_invalidate_count; /* count for cache invalidation */
- int nsc_suggestedsize; /* suggested size */
- int nsc_enabled; /* if 0, always return NOSERVER */
- int nsc_invalidate; /* command to invalidate cache */
- int nsc_pos_ttl; /* time to live for positive entries */
- int nsc_neg_ttl; /* time to live for negative entries */
- short nsc_keephot; /* number of entries to keep hot */
- short nsc_old_data_ok; /* set if expired data is acceptable */
- short nsc_check_files; /* set if file time should be checked */
- short nsc_secure_mode; /* set if pw fields to be blanked for */
- /* those other than owners */
-} nsc_stat_t;
-
+#include <nss_dbdefs.h>
/*
- * structure returned by server for all calls
+ * nscd version 2 doors interfaces
+ * The known, but private NAME_SERVICE_DOOR, filesystem name remains
+ * the same, even though the transfer contents is significantly different.
*/
-typedef struct {
- int nsc_bufferbytesused;
- int nsc_return_code;
- int nsc_errno;
-
- union {
-/*
- * If we are 64bit mode explicitly use the 32 versions, otherwise we are in
- * 32bit mode and can use the original definitions. No need to worry about
- * padding since all the sizes are preserved
- */
-#ifdef _LP64
- passwd32_t pwd;
- group32_t grp;
- hostent32_t hst;
- execstr32_t exec;
- profstr32_t prof;
- userstr32_t user;
-#else
- struct passwd pwd;
- struct group grp;
- struct hostent hst;
- execstr_t exec;
- profstr_t prof;
- userstr_t user;
+#define NAME_SERVICE_DOOR_V2 2
+#define NAME_SERVICE_DOOR_VERSION 2
+#ifndef NAME_SERVICE_DOOR
+#define NAME_SERVICE_DOOR "/var/run/name_service_door"
#endif
- nsc_stat_t stats;
- char buff[4];
- } nsc_u;
-
-} nsc_return_t;
-
-/*
- * calls look like this
- */
-
-typedef struct {
- int nsc_callnumber;
- union {
- uid_t uid;
- gid_t gid;
- char name[sizeof (int)]; /* size is indeterminate */
- struct {
- int a_type;
- int a_length;
- char a_data[sizeof (int)];
- } addr;
- struct {
- int af_family;
- int flags;
- char name[sizeof (int)]; /* size is indeterminate */
- } ipnode;
- } nsc_u;
-} nsc_call_t;
-/*
- * how the client views the call process
- */
-
-typedef union {
- nsc_call_t nsc_call;
- nsc_return_t nsc_ret;
- char nsc_buff[sizeof (int)];
-} nsc_data_t;
-
-/*
- * What each entry in the nameserver cache looks like.
- */
-
-typedef struct {
- int nsc_hits; /* number of hits */
- int nsc_status; /* flag bits */
- time_t nsc_timestamp; /* last time entry validated */
- int nsc_refcount; /* reference count */
- nsc_return_t nsc_data; /* data returned to client */
-} nsc_bucket_t;
-
-typedef struct hash_entry {
- struct hash_entry *next_entry;
- struct hash_entry *right_entry;
- struct hash_entry *left_entry;
- char *key;
- char *data;
-} hash_entry_t;
-
-typedef struct hash {
- int size;
- hash_entry_t **table;
- hash_entry_t *start;
- enum hash_type {
- String_Key = 0, Integer_Key = 1
- } hash_type;
-} hash_t;
-
-typedef struct passwd_cache {
- hash_entry_t passwd;
-} passwd_cache_t;
-
-typedef struct group_cache {
- hash_entry_t group;
-} group_cache_t;
-
-typedef struct host_cache {
- hash_entry_t host;
-} host_cache_t;
-
-/*
- * structure to handle waiting for pending name service requests
- */
-
-typedef struct waiter {
- cond_t w_waitcv;
- char **w_key;
- struct waiter *w_next, *w_prev;
-} waiter_t;
-
-/*
- * OR'D in by server to call self for updates
- */
-
-#define UPDATEBIT (1<<30)
-#define MASKUPDATEBIT(a) ((~UPDATEBIT)&(a))
-
-#define NULLCALL 0
-#define GETPWUID 1
-#define GETPWNAM 2
-#define GETGRNAM 3
-#define GETGRGID 4
-#define GETHOSTBYNAME 5
-#define GETHOSTBYADDR 6
-#define GETIPNODEBYNAME 10
-#define GETIPNODEBYADDR 11
-#define GETEXECID 12 /* for exec_attr */
-#define GETPROFNAM 13 /* for prof_attr */
-#define GETUSERNAM 14 /* for user_attr */
-
-/*
- * administrative calls
- */
-
-#define KILLSERVER 7
-#define GETADMIN 8
-#define SETADMIN 9
-
-
-/*
- * debug levels
- */
-
-#define DBG_OFF 0
-#define DBG_CANT_FIND 2
-#define DBG_NETLOOKUPS 4
-#define DBG_ALL 6
-
-/*
- * Max size name we allow to be passed to avoid
- * buffer overflow problems
- */
-#define NSCDMAXNAMELEN 255
-
-/*
- * flag bits
- */
-
-#define ST_UPDATE_PENDING 1
-
+#define NAME_SERVICE_DOOR_COOKIE ((void*)(0xdeadbeef^NAME_SERVICE_DOOR_VERSION))
/*
- * defines for client-server interaction
+ * internal APIs
*/
-#define NAME_SERVICE_DOOR_VERSION 1
-#define NAME_SERVICE_DOOR "/var/run/name_service_door"
-#define NAME_SERVICE_DOOR_COOKIE ((void*)(0xdeadbeef^NAME_SERVICE_DOOR_VERSION))
-#define UPDATE_DOOR_COOKIE ((void*)(0xdeadcafe)
-
-#define SUCCESS 0
-#define NOTFOUND -1
-#define CREDERROR -2
-#define SERVERERROR -3
-#define NOSERVER -4
+nss_status_t _nsc_trydoorcall(void **dptr, size_t *bsize, size_t *dsize);
+nss_status_t _nsc_trydoorcall_ext(void **dptr, size_t *bsize, size_t *dsize);
+int _nsc_getdoorbuf(void **dptr, size_t *bsize);
+void _nsc_resizedoorbuf(size_t bsize);
+int _nsc_proc_is_cache();
-int
-_nsc_trydoorcall(nsc_data_t **dptr, int *ndata, int *adata);
struct passwd *
_uncached_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
diff --git a/usr/src/lib/libc/port/gen/nss_common.c b/usr/src/lib/libc/port/gen/nss_common.c
index ad27e0f807..4e5f12e959 100644
--- a/usr/src/lib/libc/port/gen/nss_common.c
+++ b/usr/src/lib/libc/port/gen/nss_common.c
@@ -44,15 +44,58 @@
#undef __NSS_PRIVATE_INTERFACE
#include <nss_common.h>
+#include <nss_dbdefs.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <thread.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
#include "libc.h"
#include "tsd.h"
+#include <getxby_door.h>
+
+/*
+ * policy component function interposing definitions:
+ * nscd if so desired can interpose it's own switch functions over
+ * the internal unlocked counterparts. This will allow nscd to replace
+ * the switch policy state engine with one that uses it's internal
+ * components.
+ * Only nscd can change this through it's use of nss_config.
+ * The golden rule is: ptr == NULL checking is used in the switch to
+ * see if a function was interposed. But nscd is responsible for seeing
+ * that mutex locking to change the values are observed when the data is
+ * changed. Especially if it happens > once. The switch does not lock
+ * the pointer with mutexs.
+ */
+
+typedef struct {
+ void *p;
+#if 0
+ void (*nss_delete_fp)(nss_db_root_t *rootp);
+ nss_status_t (*nss_search_fp)(nss_db_root_t *rootp,
+ nss_db_initf_t initf, int search_fnum,
+ void *search_args);
+ void (*nss_setent_u_fp)(nss_db_root_t *,
+ nss_db_initf_t, nss_getent_t *);
+ nss_status_t (*nss_getent_u_fp)(nss_db_root_t *,
+ nss_db_initf_t, nss_getent_t *, void *);
+ void (*nss_endent_u_fp)(nss_db_root_t *,
+ nss_db_initf_t, nss_getent_t *);
+ void (*end_iter_u_fp)(nss_db_root_t *rootp,
+ struct nss_getent_context *contextp);
+#endif
+} nss_policyf_t;
+
+static mutex_t nss_policyf_lock = DEFAULTMUTEX;
+static nss_policyf_t nss_policyf_ptrs =
+ { (void *)NULL };
+
/*
+ * nsswitch db_root state machine definitions:
* The golden rule is: if you hold a pointer to an nss_db_state struct and
* you don't hold the lock, you'd better have incremented the refcount
* while you held the lock; otherwise, it may vanish or change
@@ -126,7 +169,11 @@ void _nss_db_state_destr(struct nss_db_state *);
/* === the config info hasn't changed (by comparing version numbers) */
-/* NSS_OPTIONS infrastructure BEGIN */
+/*
+ * NSS_OPTIONS/NIS_OPTIONS environment varibles data definitions:
+ * This remains for backwards compatibility. But generally nscd will
+ * decide if/how this gets used.
+ */
static int checked_env = 0; /* protected by "rootlock" */
/* allowing __nss_debug_file to be set could be a security hole. */
@@ -178,6 +225,397 @@ static struct option nis_options[] = {
{ 0, 0, 0 },
};
+/*
+ * switch configuration parameter "database" definitions:
+ * The switch maintains a simmple read/write parameter database
+ * that nscd and the switch components can use to communicate
+ * nscd data to other components for configuration or out of band
+ * [IE no in the context of a getXbyY or putXbyY operation] data.
+ * The data passed are pointers to a lock data buffer and a length.
+ * Use of this is treated as SunwPrivate between nscd and the switch
+ * unless other wise stated.
+ */
+
+typedef struct nss_cfgparam {
+ char *name;
+ mutex_t *lock;
+ void *buffer;
+ size_t length;
+} nss_cfgparam_t;
+
+typedef struct nss_cfglist {
+ char *name;
+ nss_cfgparam_t *list;
+ int count;
+ int max;
+} nss_cfglist_t;
+
+#define NSS_CFG_INCR 16
+
+static nss_cfglist_t *nss_cfg = (nss_cfglist_t *)NULL;
+static int nss_cfgcount = 0;
+static int nss_cfgmax = 0;
+static mutex_t nss_cfglock = DEFAULTMUTEX;
+
+static int nss_cfg_policy_init();
+
+/*
+ * A config parameters are in the form component:parameter
+ * as in: nss:parameter - switch (internal FE/policy/BE) parameter
+ * nscd:param - nscd application parameter
+ * ldap:param - nss_ldap BE parameter
+ * passwd:param - get/put passwd FE parameter
+ */
+
+#define NSS_CONFIG_BRK ':'
+
+/*
+ * The policy components initial parameter list
+ */
+static nss_config_t nss_policy_params[] = {
+ { "nss:policyfunc", NSS_CONFIG_ADD, &nss_policyf_lock,
+ (void *)&nss_policyf_ptrs, (size_t)sizeof (nss_policyf_t) },
+ { NULL, NSS_CONFIG_ADD, (mutex_t *)NULL, (void *)NULL, (size_t)0 },
+};
+
+/*
+ * NSS parameter configuration routines
+ */
+
+/* compare config name (component:parameter) to a component name */
+static int
+nss_cfgcn_cmp(const char *cfgname, const char *compname)
+{
+ char *c;
+ size_t len, len2;
+
+ /* this code assumes valid pointers */
+ if ((c = strchr(cfgname, NSS_CONFIG_BRK)) == NULL)
+ return (-1);
+ len = (size_t)(c - cfgname);
+ len2 = strlen(compname);
+ if (len2 != len)
+ return (-1);
+ return (strncmp(cfgname, compname, len));
+}
+
+/* init configuration arena */
+static int
+nss_cfg_init()
+{
+ int i;
+
+ /* First time caller? */
+ if (nss_cfg != NULL)
+ return (0);
+
+ /* Initialize internal tables */
+ lmutex_lock(&nss_cfglock);
+ if (nss_cfg != NULL) {
+ lmutex_unlock(&nss_cfglock);
+ return (0);
+ }
+ nss_cfg = (nss_cfglist_t *)libc_malloc(NSS_CFG_INCR *
+ sizeof (nss_cfglist_t));
+ if (nss_cfg == (nss_cfglist_t *)NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return (-1);
+ }
+ nss_cfgmax = NSS_CFG_INCR;
+ for (i = 0; i < nss_cfgmax; i++) {
+ nss_cfg[i].list = (nss_cfgparam_t *)libc_malloc(NSS_CFG_INCR *
+ sizeof (nss_cfgparam_t));
+ if (nss_cfg[i].list == (nss_cfgparam_t *)NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return (-1);
+ }
+ nss_cfg[i].max = NSS_CFG_INCR;
+ }
+
+ /* Initialize Policy Engine values */
+ lmutex_unlock(&nss_cfglock);
+ if (nss_cfg_policy_init() < 0) {
+ return (-1);
+ }
+ return (0);
+}
+
+/* find the name'd component list - create it if non-existent */
+static nss_cfglist_t *
+nss_cfgcomp_get(char *name, int add)
+{
+ nss_cfglist_t *next;
+ char *c;
+ int i, len;
+ size_t nsize;
+
+ /* Make sure system is init'd */
+ if (nss_cfg == NULL && nss_cfg_init() < 0)
+ return ((nss_cfglist_t *)NULL);
+
+ /* and check component:name validity */
+ if (name == NULL || (c = strchr(name, NSS_CONFIG_BRK)) == NULL)
+ return ((nss_cfglist_t *)NULL);
+
+ lmutex_lock(&nss_cfglock);
+ next = nss_cfg;
+ for (i = 0; i < nss_cfgcount; i++) {
+ if (next->name && nss_cfgcn_cmp(name, next->name) == 0) {
+ lmutex_unlock(&nss_cfglock);
+ return (next);
+ }
+ next++;
+ }
+ if (!add) {
+ lmutex_unlock(&nss_cfglock);
+ return (NULL);
+ }
+
+ /* not found, create a fresh one */
+ if (nss_cfgcount >= nss_cfgmax) {
+ /* realloc first */
+ nsize = (nss_cfgmax + NSS_CFG_INCR) * sizeof (nss_cfgparam_t);
+ next = (nss_cfglist_t *)libc_realloc(nss_cfg, nsize);
+ if (next == NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return ((nss_cfglist_t *)NULL);
+ }
+ (void) memset((void *)(next + nss_cfgcount), '\0',
+ NSS_CFG_INCR * sizeof (nss_cfglist_t));
+ nss_cfgmax += NSS_CFG_INCR;
+ nss_cfg = next;
+ }
+ next = nss_cfg + nss_cfgcount;
+ len = (size_t)(c - name) + 1;
+ if ((next->name = libc_malloc(len)) == NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return ((nss_cfglist_t *)NULL);
+ }
+ nss_cfgcount++;
+ (void) strlcpy(next->name, name, len);
+ lmutex_unlock(&nss_cfglock);
+ return (next);
+}
+
+/* find the name'd parameter - create it if non-existent */
+static nss_cfgparam_t *
+nss_cfgparam_get(char *name, int add)
+{
+ nss_cfglist_t *comp;
+ nss_cfgparam_t *next;
+ int count, i;
+ size_t nsize;
+
+ if ((comp = nss_cfgcomp_get(name, add)) == NULL)
+ return ((nss_cfgparam_t *)NULL);
+ lmutex_lock(&nss_cfglock);
+ count = comp->count;
+ next = comp->list;
+ for (i = 0; i < count; i++) {
+ if (next->name && strcmp(name, next->name) == 0) {
+ lmutex_unlock(&nss_cfglock);
+ return (next);
+ }
+ next++;
+ }
+ if (!add) {
+ lmutex_unlock(&nss_cfglock);
+ return (NULL);
+ }
+
+ /* not found, create a fresh one */
+ if (count >= comp->max) {
+ /* realloc first */
+ nsize = (comp->max + NSS_CFG_INCR) * sizeof (nss_cfgparam_t);
+ next = (nss_cfgparam_t *)libc_realloc(comp->list, nsize);
+ if (next == NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return ((nss_cfgparam_t *)NULL);
+ }
+ comp->max += NSS_CFG_INCR;
+ comp->list = next;
+ }
+ next = comp->list + comp->count;
+ if ((next->name = libc_strdup(name)) == NULL) {
+ errno = ENOMEM;
+ lmutex_unlock(&nss_cfglock);
+ return ((nss_cfgparam_t *)NULL);
+ }
+ comp->count++;
+ lmutex_unlock(&nss_cfglock);
+ return (next);
+}
+
+/* find the name'd parameter - delete it if it exists */
+static void
+nss_cfg_del(nss_config_t *cfgp)
+{
+ char *name;
+ nss_cfglist_t *comp;
+ nss_cfgparam_t *next, *cur;
+ int count, i, j;
+
+ /* exit if component name does not already exist */
+ if ((name = cfgp->name) == NULL ||
+ (comp = nss_cfgcomp_get(name, 0)) == NULL)
+ return;
+
+ /* find it */
+ lmutex_lock(&nss_cfglock);
+ count = comp->count;
+ next = comp->list;
+ for (i = 0; i < count; i++) {
+ if (next->name && strcmp(name, next->name) == 0) {
+ break; /* found it... */
+ }
+ next++;
+ }
+ if (i >= count) {
+ /* not found, already deleted */
+ lmutex_unlock(&nss_cfglock);
+ return;
+ }
+
+ /* copy down the remaining parameters, and clean up */
+ /* don't try to clean up component tables */
+ cur = next;
+ next++;
+ for (j = i+1; j < count; j++) {
+ *cur = *next;
+ cur++;
+ next++;
+ }
+ /* erase the last one */
+ if (cur->name) {
+ libc_free(cur->name);
+ cur->name = (char *)NULL;
+ }
+ cur->lock = (mutex_t *)NULL;
+ cur->buffer = (void *)NULL;
+ cur->length = 0;
+ comp->count--;
+ lmutex_unlock(&nss_cfglock);
+}
+
+static int
+nss_cfg_get(nss_config_t *next)
+{
+ nss_cfgparam_t *param;
+
+ errno = 0;
+ if ((param = nss_cfgparam_get(next->name, 0)) == NULL)
+ return (-1);
+ next->lock = param->lock;
+ next->buffer = param->buffer;
+ next->length = param->length;
+ return (0);
+}
+
+static int
+nss_cfg_put(nss_config_t *next, int add)
+{
+ nss_cfgparam_t *param;
+
+ errno = 0;
+ if ((param = nss_cfgparam_get(next->name, add)) == NULL)
+ return (-1);
+ param->lock = next->lock;
+ param->buffer = next->buffer;
+ param->length = next->length;
+ return (0);
+}
+
+/*
+ * Policy engine configurator - set and get interface
+ * argument is a NULL terminated list of set/get requests
+ * with input/result buffers and lengths. nss_cname is the
+ * specifier of a set or get operation and the property being
+ * managed. The intent is limited functions and expandability.
+ */
+
+nss_status_t
+nss_config(nss_config_t **plist, int cnt)
+{
+ nss_config_t *next;
+ int i;
+
+ /* interface is only available to nscd */
+ if (_nsc_proc_is_cache() <= 0) {
+ return (NSS_UNAVAIL);
+ }
+ if (plist == NULL || cnt <= 0)
+ return (NSS_SUCCESS);
+ for (i = 0; i < cnt; i++) {
+ next = plist[i];
+ if (next == NULL)
+ break;
+ if (next->name == NULL) {
+ errno = EFAULT;
+ return (NSS_ERROR);
+ }
+ switch (next->cop) {
+ case NSS_CONFIG_GET:
+ /* get current lock/buffer/length fields */
+ if (nss_cfg_get(next) < 0) {
+ return (NSS_ERROR);
+ }
+ break;
+ case NSS_CONFIG_PUT:
+ /* set new lock/buffer/length fields */
+ if (nss_cfg_put(next, 0) < 0) {
+ return (NSS_ERROR);
+ }
+ break;
+ case NSS_CONFIG_ADD:
+ /* add parameter & set new lock/buffer/length fields */
+ if (nss_cfg_put(next, 1) < 0) {
+ return (NSS_ERROR);
+ }
+ break;
+ case NSS_CONFIG_DELETE:
+ /* delete parameter - should always work... */
+ nss_cfg_del(next);
+ break;
+ case NSS_CONFIG_LIST:
+ break;
+ default:
+ continue;
+ }
+ }
+ return (NSS_SUCCESS);
+}
+
+/*
+ * This routine is called immediately after nss_cfg_init but prior to
+ * any commands from nscd being processed. The intent here is to
+ * initialize the nss:* parameters allowed by the policy component
+ * so that nscd can then proceed and modify them if so desired.
+ *
+ * We know we can only get here if we are nscd so we can skip the
+ * preliminaries.
+ */
+
+static int
+nss_cfg_policy_init()
+{
+ nss_config_t *next = &nss_policy_params[0];
+
+ for (; next && next->name != NULL; next++) {
+ if (nss_cfg_put(next, 1) < 0)
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * NSS_OPTION & NIS_OPTION environment variable functions
+ */
+
static
void
set_option(struct option *opt, char *name, char *val)
@@ -293,9 +731,12 @@ __nis_get_environment()
return;
__parse_environment(nis_options, p);
}
-/* NSS_OPTIONS/NIS_OPTIONS infrastructure END */
+/*
+ * Switch policy component backend state machine functions
+ */
+
static nss_backend_t *
nss_get_backend_u(nss_db_root_t **rootpp, struct nss_db_state *s, int n_src)
{
@@ -512,6 +953,10 @@ _nss_src_state_destr(struct nss_src_state *src, int max_dormant)
void
_nss_db_state_destr(struct nss_db_state *s)
{
+
+ if (s == NULL)
+ return;
+
/* === _private_mutex_destroy(&s->orphan_root.lock); */
if (s->p.cleanup != 0) {
(*s->p.cleanup)(&s->p);
@@ -531,20 +976,6 @@ _nss_db_state_destr(struct nss_db_state *s)
libc_free(s);
}
-void
-nss_delete(nss_db_root_t *rootp)
-{
- struct nss_db_state *s;
-
- NSS_ROOTLOCK(rootp, &s);
- if (s == 0) {
- NSS_UNLOCK(rootp);
- } else {
- rootp->s = 0;
- NSS_UNREF_UNLOCK(rootp, s);
- }
-}
-
/*
* _nss_status_vec() returns a bit vector of all status codes returned during
@@ -675,6 +1106,28 @@ retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp)
return (0);
}
+/*
+ * Switch policy component functional interfaces
+ */
+
+void
+nss_delete(nss_db_root_t *rootp)
+{
+ struct nss_db_state *s;
+
+ /* no name service cache daemon divert here */
+ /* local nss_delete decrements state reference counts */
+ /* and may free up opened switch resources. */
+
+ NSS_ROOTLOCK(rootp, &s);
+ if (s == 0) {
+ NSS_UNLOCK(rootp);
+ } else {
+ rootp->s = 0;
+ NSS_UNREF_UNLOCK(rootp, s);
+ }
+}
+
nss_status_t
nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
void *search_args)
@@ -682,7 +1135,17 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
nss_status_t res = NSS_UNAVAIL;
struct nss_db_state *s;
int n_src;
- unsigned int *status_vec_p = _nss_status_vec_p();
+ unsigned int *status_vec_p;
+
+ /* name service cache daemon divert */
+ res = _nsc_search(rootp, initf, search_fnum, search_args);
+ if (res != NSS_TRYLOCAL)
+ return (res);
+
+ /* fall through - process locally */
+ errno = 0; /* just in case ... */
+ res = NSS_UNAVAIL;
+ status_vec_p = _nss_status_vec_p();
if (status_vec_p == NULL) {
return (NSS_UNAVAIL);
@@ -763,7 +1226,7 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
/*
- * Start of nss_setent()/nss_getent()/nss_endent()
+ * Start of nss_{setent|getent|endent}
*/
/*
@@ -772,16 +1235,31 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
* database; in practice, since Posix and UI have helpfully said that
* getent() state is global rather than, say, per-thread or user-supplied,
* we have at most one of these per nss_db_state.
+ * XXX ? Is this statement still true?
+ *
+ * NSS2 - a client's context is maintained as a cookie delivered by and
+ * passed to nscd. The cookie is a 64 bit (nssuint_t) unique opaque value
+ * created by nscd.
+ * cookie states:
+ * NSCD_NEW_COOKIE - cookie value uninitialized
+ * NSCD_LOCAL_COOKIE - setent is a local setent
+ * all other - NSCD unique opaque id for this setent
+ * A client's context is also associated with a seq_num. This is a nscd
+ * opaque 64 bit (nssuint_t) value passed with a cookie, and used to by nscd
+ * to validate the sequencing of the context. The client treats this as
+ * a pass through value.
+ *
+ * XXX ?? Use Cookie as cross-check info so that we can detect an
+ * nss_context that missed an nss_delete() or similar.
*/
struct nss_getent_context {
int n_src; /* >= max_src ==> end of sequence */
nss_backend_t *be;
struct nss_db_state *s;
- /*
- * XXX ?? Should contain enough cross-check info that we can detect an
- * nss_context that missed an nss_delete() or similar.
- */
+ nssuint_t cookie;
+ nssuint_t seq_num;
+ nss_db_params_t param;
};
static void nss_setent_u(nss_db_root_t *,
@@ -834,7 +1312,7 @@ nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp)
/*
* Each of the _u versions of the nss interfaces assume that the context
- * lock is held.
+ * lock is held. No need to divert to nscd. Private to local sequencing.
*/
static void
@@ -864,21 +1342,31 @@ static void
nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
nss_getent_t *contextpp)
{
+ nss_status_t status;
struct nss_db_state *s;
struct nss_getent_context *contextp;
nss_backend_t *be;
int n_src;
+ /* setup process wide context while locked */
if ((contextp = contextpp->ctx) == 0) {
if ((contextp = libc_malloc(sizeof (*contextp))) == 0) {
return;
}
contextpp->ctx = contextp;
+ contextp->cookie = NSCD_NEW_COOKIE; /* cookie init */
+ contextp->seq_num = 0; /* seq_num init */
s = 0;
} else {
s = contextp->s;
}
+ /* name service cache daemon divert */
+ status = _nsc_setent_u(rootp, initf, contextpp);
+ if (status != NSS_TRYLOCAL)
+ return;
+
+ /* fall through - process locally */
if (s == 0) {
NSS_LOCK_CHECK(rootp, initf, &s);
if (s == 0) {
@@ -935,6 +1423,7 @@ static nss_status_t
nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
nss_getent_t *contextpp, void *args)
{
+ nss_status_t status;
struct nss_db_state *s;
struct nss_getent_context *contextp;
int n_src;
@@ -947,6 +1436,12 @@ nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
return (NSS_UNAVAIL);
}
}
+ /* name service cache daemon divert */
+ status = _nsc_getent_u(rootp, initf, contextpp, args);
+ if (status != NSS_TRYLOCAL)
+ return (status);
+
+ /* fall through - process locally */
s = contextp->s;
n_src = contextp->n_src;
be = contextp->be;
@@ -1009,12 +1504,25 @@ static void
nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
nss_getent_t *contextpp)
{
+ nss_status_t status;
struct nss_getent_context *contextp;
if ((contextp = contextpp->ctx) == 0) {
/* nss_endent() on an unused context is a no-op */
return;
}
+
+ /* notify name service cache daemon */
+ status = _nsc_endent_u(rootp, initf, contextpp);
+ if (status != NSS_TRYLOCAL) {
+ /* clean up */
+ libc_free(contextp);
+ contextpp->ctx = 0;
+ return;
+ }
+
+ /* fall through - process locally */
+
/*
* Existing code (BSD, SunOS) works in such a way that getXXXent()
* following an endXXXent() behaves as though the user had invoked
@@ -1033,3 +1541,698 @@ nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
libc_free(contextp);
contextpp->ctx = 0;
}
+
+/*
+ * pack dbd data into header
+ * Argment pointers assumed valid.
+ * poff offset position pointer
+ * IN = starting offset for dbd header
+ * OUT = starting offset for next section
+ */
+
+static nss_status_t
+nss_pack_dbd(void *buffer, size_t bufsize, nss_db_params_t *p, size_t *poff)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_dbd_t *pdbd;
+ size_t off = *poff;
+ size_t len, blen;
+ size_t n, nc, dc;
+ char *bptr;
+
+ pbuf->dbd_off = (nssuint_t)off;
+ bptr = (char *)buffer + off;
+ blen = bufsize - off;
+ len = sizeof (nss_dbd_t);
+
+ n = nc = dc = 0;
+ if (p->name == NULL) {
+ errno = ERANGE; /* actually EINVAL */
+ return (NSS_ERROR);
+ }
+
+ /* if default config not specified, the flag should be reset */
+ if (p->default_config == NULL) {
+ p->default_config = "<NULL>";
+ p->flags = p->flags & ~NSS_USE_DEFAULT_CONFIG;
+ }
+
+ n = strlen(p->name) + 1;
+ dc = strlen(p->default_config) + 1;
+ if (n < 2 || dc < 2) { /* What no DB? */
+ errno = ERANGE; /* actually EINVAL */
+ return (NSS_ERROR);
+ }
+ if (p->config_name != NULL) {
+ nc = strlen(p->config_name) + 1;
+ }
+ if ((len + n + nc + dc) >= blen) {
+ errno = ERANGE; /* actually EINVAL */
+ return (NSS_ERROR);
+ }
+
+ pdbd = (nss_dbd_t *)((void *)bptr);
+ bptr += len;
+ pdbd->flags = p->flags;
+ pdbd->o_name = len;
+ (void) strlcpy(bptr, p->name, n);
+ len += n;
+ bptr += n;
+ if (nc == 0) {
+ pdbd->o_config_name = 0;
+ } else {
+ pdbd->o_config_name = len;
+ (void) strlcpy(bptr, p->config_name, nc);
+ bptr += nc;
+ len += nc;
+ }
+ pdbd->o_default_config = len;
+ (void) strlcpy(bptr, p->default_config, dc);
+ len += dc;
+ pbuf->dbd_len = (nssuint_t)len;
+ off += ROUND_UP(len, sizeof (nssuint_t));
+ *poff = off;
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Switch packed and _nsc (switch->nscd) interfaces
+ * Return: NSS_SUCCESS (OK to proceed), NSS_ERROR, NSS_NOTFOUND
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_pack(void *buffer, size_t bufsize, nss_db_root_t *rootp,
+ nss_db_initf_t initf, int search_fnum, void *search_args)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_XbyY_args_t *in = (nss_XbyY_args_t *)search_args;
+ nss_db_params_t tparam = { 0 };
+ nss_status_t ret = NSS_ERROR;
+ const char *dbn;
+ size_t blen, len, off = 0;
+ char *bptr;
+ nssuint_t *uptr;
+ struct nss_groupsbymem *gbm;
+
+ if (pbuf == NULL || in == NULL || initf == (nss_db_initf_t)NULL) {
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+ tparam.cleanup = NULL;
+ (*initf)(&tparam);
+ if ((dbn = tparam.name) == 0) {
+ if (tparam.cleanup != 0)
+ (tparam.cleanup)(&tparam);
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+
+ /* init buffer header */
+ pbuf->pbufsiz = (nssuint_t)bufsize;
+ pbuf->p_ruid = (uint32_t)getuid();
+ pbuf->p_euid = (uint32_t)geteuid();
+ pbuf->p_version = NSCD_HEADER_REV;
+ pbuf->p_status = 0;
+ pbuf->p_errno = 0;
+ pbuf->p_herrno = 0;
+
+ /* possible audituser init */
+ if (strcmp(dbn, NSS_DBNAM_AUTHATTR) == 0 && in->h_errno != 0)
+ pbuf->p_herrno = (uint32_t)in->h_errno;
+
+ pbuf->libpriv = 0;
+
+ off = sizeof (nss_pheader_t);
+
+ /* setup getXbyY operation - database and sub function */
+ pbuf->nss_dbop = (uint32_t)search_fnum;
+ ret = nss_pack_dbd(buffer, bufsize, &tparam, &off);
+ if (ret != NSS_SUCCESS) {
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+ ret = NSS_ERROR;
+ /* setup request key */
+ pbuf->key_off = (nssuint_t)off;
+ bptr = (char *)buffer + off;
+ blen = bufsize - off;
+ /* use key2str if provided, else call default getXbyY packer */
+ if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
+ /* This has to run locally due to backend knowledge */
+ if (search_fnum == NSS_DBOP_NETGROUP_SET) {
+ errno = 0;
+ return (NSS_TRYLOCAL);
+ }
+ /* use default packer for known getXbyY ops */
+ ret = nss_default_key2str(bptr, blen, in, dbn,
+ search_fnum, &len);
+ } else if (in->key2str == NULL ||
+ (search_fnum == NSS_DBOP_GROUP_BYMEMBER &&
+ strcmp(dbn, NSS_DBNAM_GROUP) == 0)) {
+ /* use default packer for known getXbyY ops */
+ ret = nss_default_key2str(bptr, blen, in, dbn,
+ search_fnum, &len);
+ } else {
+ ret = (*in->key2str)(bptr, blen, &in->key, &len);
+ }
+ if (tparam.cleanup != 0)
+ (tparam.cleanup)(&tparam);
+ if (ret != NSS_SUCCESS) {
+ errno = ERANGE; /* actually ENOMEM */
+ return (ret);
+ }
+ pbuf->key_len = (nssuint_t)len;
+ off += ROUND_UP(len, sizeof (nssuint_t));
+
+ pbuf->data_off = (nssuint_t)off;
+ pbuf->data_len = (nssuint_t)(bufsize - off);
+ /*
+ * Prime data return with first result if
+ * the first result is passed in
+ * [_getgroupsbymember oddness]
+ */
+ gbm = (struct nss_groupsbymem *)search_args;
+ if (search_fnum == NSS_DBOP_GROUP_BYMEMBER &&
+ strcmp(dbn, NSS_DBNAM_GROUP) == 0 && gbm->numgids == 1) {
+ uptr = (nssuint_t *)((void *)((char *)buffer + off));
+ *uptr = (nssuint_t)gbm->gid_array[0];
+ }
+
+ errno = 0; /* just in case ... */
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Switch packed and _nsc (switch->nscd) {set/get/end}ent interfaces
+ * Return: NSS_SUCCESS (OK to proceed), NSS_ERROR, NSS_NOTFOUND
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_pack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp,
+ nss_db_initf_t initf, nss_getent_t *contextpp)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ struct nss_getent_context *contextp = contextpp->ctx;
+ nss_status_t ret = NSS_ERROR;
+ size_t blen, len = 0, off = 0;
+ char *bptr;
+ nssuint_t *nptr;
+
+ if (pbuf == NULL || initf == (nss_db_initf_t)NULL) {
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+
+ /* init buffer header */
+ pbuf->pbufsiz = (nssuint_t)bufsize;
+ pbuf->p_ruid = (uint32_t)getuid();
+ pbuf->p_euid = (uint32_t)geteuid();
+ pbuf->p_version = NSCD_HEADER_REV;
+ pbuf->p_status = 0;
+ pbuf->p_errno = 0;
+ pbuf->p_herrno = 0;
+ pbuf->libpriv = 0;
+
+ off = sizeof (nss_pheader_t);
+
+ /* setup getXXXent operation - database and sub function */
+ pbuf->nss_dbop = (uint32_t)0; /* iterators have no dbop */
+ ret = nss_pack_dbd(buffer, bufsize, &contextp->param, &off);
+ if (ret != NSS_SUCCESS) {
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+ ret = NSS_ERROR;
+ off += ROUND_UP(len, sizeof (nssuint_t));
+
+ pbuf->key_off = (nssuint_t)off;
+ bptr = (char *)buffer + off;
+ blen = bufsize - off;
+ len = (size_t)(sizeof (nssuint_t) * 2);
+ if (len >= blen) {
+ errno = ERANGE; /* actually EINVAL */
+ return (ret);
+ }
+ nptr = (nssuint_t *)((void *)bptr);
+ *nptr++ = contextp->cookie;
+ *nptr = contextp->seq_num;
+ pbuf->key_len = (nssuint_t)len;
+
+ off += len;
+ pbuf->data_off = (nssuint_t)off;
+ pbuf->data_len = (nssuint_t)(bufsize - off);
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Unpack packed arguments buffer
+ * Return: status, errnos and results from requested operation.
+ *
+ * NOTES: When getgroupsbymember is being processed in the NSCD backend,
+ * or via the backwards compatibility interfaces then the standard
+ * str2group API is used in conjunction with process_cstr. When,
+ * processing a returned buffer, in NSS2 the return results are the
+ * already digested groups array. Therefore, unpack the digested results
+ * back to the return buffer.
+ *
+ * Note: the digested results are nssuint_t quantities. _getgroupsbymember
+ * digests int quantities. Therefore convert. Assume input is in nssuint_t
+ * quantities. Store in an int array... Assume gid's are <= 32 bits...
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_unpack(void *buffer, size_t bufsize, nss_db_root_t *rootp,
+ nss_db_initf_t initf, int search_fnum, void *search_args)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_XbyY_args_t *in = (nss_XbyY_args_t *)search_args;
+ nss_dbd_t *pdbd;
+ char *dbn;
+ nss_status_t status;
+ char *buf;
+ int len;
+ int ret;
+ int i;
+ gid_t *gidp;
+ nssuint_t *uptr;
+ struct nss_groupsbymem *arg;
+
+
+ if (pbuf == NULL || in == NULL)
+ return (-1);
+ status = pbuf->p_status;
+ /* if error - door's switch error */
+ /* extended data could contain additional information? */
+ if (status != NSS_SUCCESS) {
+ in->h_errno = (int)pbuf->p_herrno;
+ if (pbuf->p_errno == ERANGE)
+ in->erange = 1;
+ return (status);
+ }
+
+ if (pbuf->data_off == 0 || pbuf->data_len == 0)
+ return (NSS_NOTFOUND);
+
+ buf = (char *)buffer + pbuf->data_off;
+ len = pbuf->data_len;
+
+ /* sidestep odd cases */
+ pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
+ dbn = (char *)pdbd + pdbd->o_name;
+ if (search_fnum == NSS_DBOP_GROUP_BYMEMBER) {
+ if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
+ arg = (struct nss_groupsbymem *)in;
+ /* copy returned gid array from returned nscd buffer */
+ i = len / sizeof (nssuint_t);
+ /* not enough buffer */
+ if (i > arg->maxgids) {
+ i = arg->maxgids;
+ }
+ arg->numgids = i;
+ gidp = arg->gid_array;
+ uptr = (nssuint_t *)((void *)buf);
+ while (--i >= 0)
+ *gidp++ = (gid_t)*uptr++;
+ return (NSS_SUCCESS);
+ }
+ }
+ if (search_fnum == NSS_DBOP_NETGROUP_IN) {
+ if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
+ struct nss_innetgr_args *arg =
+ (struct nss_innetgr_args *)in;
+
+ if (pbuf->p_status == NSS_SUCCESS) {
+ arg->status = NSS_NETGR_FOUND;
+ return (NSS_SUCCESS);
+ } else {
+ arg->status = NSS_NETGR_NO;
+ return (NSS_NOTFOUND);
+ }
+ }
+ }
+
+ /* process the normal cases */
+ /* marshall data directly into users buffer */
+ ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer,
+ in->buf.buflen);
+ if (ret == NSS_STR_PARSE_ERANGE) {
+ in->returnval = 0;
+ in->returnlen = 0;
+ in->erange = 1;
+ ret = NSS_NOTFOUND;
+ } else if (ret == NSS_STR_PARSE_SUCCESS) {
+ in->returnval = in->buf.result;
+ in->returnlen = len;
+ ret = NSS_SUCCESS;
+ }
+ in->h_errno = (int)pbuf->p_herrno;
+ return ((nss_status_t)ret);
+}
+
+/*
+ * Unpack a returned packed {set,get,end}ent arguments buffer
+ * Return: status, errnos, cookie info and results from requested operation.
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_unpack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp,
+ nss_db_initf_t initf, nss_getent_t *contextpp, void *args)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_XbyY_args_t *in = (nss_XbyY_args_t *)args;
+ struct nss_getent_context *contextp = contextpp->ctx;
+ nssuint_t *nptr;
+ nssuint_t cookie;
+ nss_status_t status;
+ char *buf;
+ int len;
+ int ret;
+
+ if (pbuf == NULL)
+ return (-1);
+ status = pbuf->p_status;
+ /* if error - door's switch error */
+ /* extended data could contain additional information? */
+ if (status != NSS_SUCCESS)
+ return (status);
+
+ /* unpack assigned cookie from SET/GET/END request */
+ if (pbuf->key_off == 0 ||
+ pbuf->key_len != (sizeof (nssuint_t) * 2))
+ return (NSS_NOTFOUND);
+
+ nptr = (nssuint_t *)((void *)((char *)buffer + pbuf->key_off));
+ cookie = contextp->cookie;
+ if (cookie != NSCD_NEW_COOKIE && cookie != *nptr) {
+ /* Should either be new or a match, else error */
+ return (NSS_NOTFOUND);
+ }
+ /* save away for the next ent request */
+ contextp->cookie = *nptr++;
+ contextp->seq_num = *nptr;
+
+ /* All done if no marshalling is expected {set,end}ent */
+ if (args == NULL)
+ return (NSS_SUCCESS);
+
+ /* unmarshall the data */
+ if (pbuf->data_off == 0 || pbuf->data_len == 0)
+ return (NSS_NOTFOUND);
+ buf = (char *)buffer + pbuf->data_off;
+
+ len = pbuf->data_len;
+
+ /* marshall data directly into users buffer */
+ ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer,
+ in->buf.buflen);
+ if (ret == NSS_STR_PARSE_ERANGE) {
+ in->returnval = 0;
+ in->returnlen = 0;
+ in->erange = 1;
+ } else if (ret == NSS_STR_PARSE_SUCCESS) {
+ in->returnval = in->buf.result;
+ in->returnlen = len;
+ }
+ in->h_errno = (int)pbuf->p_herrno;
+ return ((nss_status_t)ret);
+}
+
+/*
+ * Start of _nsc_{search|setent_u|getent_u|endent_u} NSCD interposition funcs
+ */
+
+nss_status_t
+_nsc_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
+ void *search_args)
+{
+ nss_pheader_t *pbuf;
+ void *doorptr = NULL;
+ size_t bufsize = 0;
+ size_t datasize = 0;
+ nss_status_t status;
+
+ if (_nsc_proc_is_cache() > 0) {
+ /* internal nscd call - don't use the door */
+ return (NSS_TRYLOCAL);
+ }
+
+ /* standard client calls nscd code */
+ if (search_args == NULL)
+ return (NSS_NOTFOUND);
+
+ /* get the door buffer & configured size */
+ bufsize = ((nss_XbyY_args_t *)search_args)->buf.buflen;
+ if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
+ return (NSS_TRYLOCAL);
+ if (doorptr == NULL || bufsize == 0)
+ return (NSS_TRYLOCAL);
+
+ pbuf = (nss_pheader_t *)doorptr;
+ /* pack argument and request into door buffer */
+ pbuf->nsc_callnumber = NSCD_SEARCH;
+ /* copy relevant door request info into door buffer */
+ status = nss_pack((void *)pbuf, bufsize, rootp,
+ initf, search_fnum, search_args);
+
+ /* Packing error return error results */
+ if (status != NSS_SUCCESS)
+ return (status);
+
+ /* transfer packed switch request to nscd via door */
+ /* data_off can be used because it is header+dbd_len+key_len */
+ datasize = pbuf->data_off;
+ status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
+
+ /* If unsuccessful fallback to standard nss logic */
+ if (status != NSS_SUCCESS) {
+ /*
+ * check if doors reallocated the memory underneath us
+ * if they did munmap it or suffer a memory leak
+ */
+ if (doorptr != (void *)pbuf) {
+ _nsc_resizedoorbuf(bufsize);
+ munmap((void *)doorptr, bufsize);
+ }
+ return (NSS_TRYLOCAL);
+ }
+
+ /* unpack and marshall data/errors to user structure */
+ /* set any error conditions */
+ status = nss_unpack((void *)doorptr, bufsize, rootp, initf,
+ search_fnum, search_args);
+ /*
+ * check if doors reallocated the memory underneath us
+ * if they did munmap it or suffer a memory leak
+ */
+ if (doorptr != (void *)pbuf) {
+ _nsc_resizedoorbuf(bufsize);
+ munmap((void *)doorptr, bufsize);
+ }
+ return (status);
+}
+
+/*
+ * contact nscd for a cookie or to reset an existing cookie
+ * if nscd fails (NSS_TRYLOCAL) then set cookie to -1 and
+ * continue diverting to local
+ */
+nss_status_t
+_nsc_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ nss_status_t status = NSS_TRYLOCAL;
+ struct nss_getent_context *contextp = contextpp->ctx;
+ nss_pheader_t *pbuf;
+ void *doorptr = NULL;
+ size_t bufsize = 0;
+ size_t datasize = 0;
+
+ /* return if already in local mode */
+ if (contextp->cookie == NSCD_LOCAL_COOKIE)
+ return (NSS_TRYLOCAL);
+
+ if (_nsc_proc_is_cache() > 0) {
+ /* internal nscd call - don't try to use the door */
+ contextp->cookie = NSCD_LOCAL_COOKIE;
+ return (NSS_TRYLOCAL);
+ }
+
+ /* get the door buffer & configured size */
+ if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0) {
+ contextp->cookie = NSCD_LOCAL_COOKIE;
+ return (NSS_TRYLOCAL);
+ }
+ if (doorptr == NULL || bufsize == 0) {
+ contextp->cookie = NSCD_LOCAL_COOKIE;
+ return (NSS_TRYLOCAL);
+ }
+
+ pbuf = (nss_pheader_t *)doorptr;
+ pbuf->nsc_callnumber = NSCD_SETENT;
+
+ contextp->param.cleanup = NULL;
+ (*initf)(&contextp->param);
+ if (contextp->param.name == 0) {
+ if (contextp->param.cleanup != 0)
+ (contextp->param.cleanup)(&contextp->param);
+ errno = ERANGE; /* actually EINVAL */
+ return (NSS_ERROR);
+ }
+
+ /* pack relevant setent request info into door buffer */
+ status = nss_pack_ent((void *)pbuf, bufsize, rootp,
+ initf, contextpp);
+ if (status != NSS_SUCCESS)
+ return (status);
+
+ /* transfer packed switch request to nscd via door */
+ /* data_off can be used because it is header+dbd_len+key_len */
+ datasize = pbuf->data_off;
+ status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
+
+ /* If fallback to standard nss logic (door failure) if possible */
+ if (status != NSS_SUCCESS) {
+ if (contextp->cookie == NSCD_NEW_COOKIE) {
+ contextp->cookie = NSCD_LOCAL_COOKIE;
+ return (NSS_TRYLOCAL);
+ }
+ return (NSS_UNAVAIL);
+ }
+ /* unpack returned cookie stash it away */
+ status = nss_unpack_ent((void *)doorptr, bufsize, rootp,
+ initf, contextpp, NULL);
+ /*
+ * check if doors reallocated the memory underneath us
+ * if they did munmap it or suffer a memory leak
+ */
+ if (doorptr != (void *)pbuf) {
+ _nsc_resizedoorbuf(bufsize);
+ munmap((void *)doorptr, bufsize);
+ }
+ return (status);
+}
+
+nss_status_t
+_nsc_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp, void *args)
+{
+ nss_status_t status = NSS_TRYLOCAL;
+ struct nss_getent_context *contextp = contextpp->ctx;
+ nss_pheader_t *pbuf;
+ void *doorptr = NULL;
+ size_t bufsize = 0;
+ size_t datasize = 0;
+
+ /* return if already in local mode */
+ if (contextp->cookie == NSCD_LOCAL_COOKIE)
+ return (NSS_TRYLOCAL);
+
+ /* _nsc_setent_u already checked for nscd local case ... proceed */
+ if (args == NULL)
+ return (NSS_NOTFOUND);
+
+ /* get the door buffer & configured size */
+ bufsize = ((nss_XbyY_args_t *)args)->buf.buflen;
+ if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
+ return (NSS_UNAVAIL);
+ if (doorptr == NULL || bufsize == 0)
+ return (NSS_UNAVAIL);
+
+ pbuf = (nss_pheader_t *)doorptr;
+ pbuf->nsc_callnumber = NSCD_GETENT;
+
+ /* pack relevant setent request info into door buffer */
+ status = nss_pack_ent((void *)pbuf, bufsize, rootp,
+ initf, contextpp);
+ if (status != NSS_SUCCESS)
+ return (status);
+
+ /* transfer packed switch request to nscd via door */
+ /* data_off can be used because it is header+dbd_len+key_len */
+ datasize = pbuf->data_off;
+ status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
+
+ /* If fallback to standard nss logic (door failure) if possible */
+ if (status != NSS_SUCCESS) {
+ if (contextp->cookie == NSCD_NEW_COOKIE) {
+ contextp->cookie = NSCD_LOCAL_COOKIE;
+ return (NSS_TRYLOCAL);
+ }
+ return (NSS_UNAVAIL);
+ }
+ /* check error, unpack and process results */
+ status = nss_unpack_ent((void *)doorptr, bufsize, rootp,
+ initf, contextpp, args);
+ /*
+ * check if doors reallocated the memory underneath us
+ * if they did munmap it or suffer a memory leak
+ */
+ if (doorptr != (void *)pbuf) {
+ _nsc_resizedoorbuf(bufsize);
+ munmap((void *)doorptr, bufsize);
+ }
+ return (status);
+}
+
+nss_status_t
+_nsc_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
+ nss_getent_t *contextpp)
+{
+ nss_status_t status = NSS_TRYLOCAL;
+ struct nss_getent_context *contextp = contextpp->ctx;
+ nss_pheader_t *pbuf;
+ void *doorptr = NULL;
+ size_t bufsize = 0;
+ size_t datasize = 0;
+
+ /* return if already in local mode */
+ if (contextp->cookie == NSCD_LOCAL_COOKIE)
+ return (NSS_TRYLOCAL);
+
+ /* _nsc_setent_u already checked for nscd local case ... proceed */
+
+ /* get the door buffer & configured size */
+ if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
+ return (NSS_UNAVAIL);
+ if (doorptr == NULL || bufsize == 0)
+ return (NSS_UNAVAIL);
+
+ /* pack up a NSCD_ENDGET request passing in the cookie */
+ pbuf = (nss_pheader_t *)doorptr;
+ pbuf->nsc_callnumber = NSCD_ENDENT;
+
+ /* pack relevant setent request info into door buffer */
+ status = nss_pack_ent((void *)pbuf, bufsize, rootp,
+ initf, contextpp);
+ if (status != NSS_SUCCESS)
+ return (status);
+
+ /* transfer packed switch request to nscd via door */
+ /* data_off can be used because it is header+dbd_len+key_len */
+ datasize = pbuf->data_off;
+ (void) _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
+
+ /* error codes & unpacking ret values don't matter. We're done */
+
+ /*
+ * check if doors reallocated the memory underneath us
+ * if they did munmap it or suffer a memory leak
+ */
+ if (doorptr != (void *)pbuf) {
+ _nsc_resizedoorbuf(bufsize);
+ munmap((void *)doorptr, bufsize);
+ }
+
+ /* clean up initf setup */
+ if (contextp->param.cleanup != 0)
+ (contextp->param.cleanup)(&contextp->param);
+ contextp->param.cleanup = NULL;
+
+ /* clear cookie */
+ contextp->cookie = NSCD_NEW_COOKIE;
+ return (NSS_SUCCESS);
+}
diff --git a/usr/src/lib/libc/port/gen/nss_dbdefs.c b/usr/src/lib/libc/port/gen/nss_dbdefs.c
index 510c0bcbb6..687c3a9711 100644
--- a/usr/src/lib/libc/port/gen/nss_dbdefs.c
+++ b/usr/src/lib/libc/port/gen/nss_dbdefs.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,19 +19,34 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "synonyms.h"
+#include <mtlib.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nss_dbdefs.h>
#include <limits.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <thread.h>
+/* headers for key2str/str2key routines */
+#include <sys/ethernet.h>
+#include <exec_attr.h>
+#include <grp.h>
+
+/*
+ * functions in nss_dbdefs.c deal more with the mechanics of
+ * the data structures like nss_XbyY_args_t and the interaction
+ * with the packed buffers etc. versus the mechanics of the
+ * actual policy component operations such as nss_search sequencing.
+ */
/*
* ALIGN? is there an official definition of this?
@@ -165,3 +179,1104 @@ _nss_netdb_aliases(const char *instr, int lenstr, char *buffer, int buflen)
*aliasp++ = 0;
return (alias_start);
}
+
+
+/*
+ * pack well known getXbyY keys to packed buffer prior to the door_call
+ * to nscd. Some consideration is given to ordering the tests based on
+ * usage. Note: buf is nssuint_t aligned.
+ */
+
+typedef struct {
+ const char *name; /* NSS_DBNAM_* */
+ const char *defconf; /* NSS_DEFCONF_* */
+ const char *initfn; /* init function name */
+ const char *strfn; /* str2X function name */
+ const char *cstrfn; /* cstr2X function name */
+ uint32_t dbop; /* NSS_DBOP_* */
+ const char *tostr; /* key2str cvt str */
+} getXbyY_to_dbop_t;
+
+#define NSS_MK_GETXYDBOP(x, y, f, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
+ NULL, NSS_DBOP_##x##_##y, (e) }
+
+#define NSS_MK_GETXYDBOPA(x, a, f, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
+ NULL, NSS_DBOP_##a, (e) }
+
+#define NSS_MK_GETXYDBOPB(x, b, a, f, s, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##b, "_nss_initf_" f, s, \
+ NULL, NSS_DBOP_##a, (e) }
+
+#define NSS_MK_GETXYDBOPC(x, a, f, s, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
+ NULL, NSS_DBOP_##x##_##a, (e) }
+
+#define NSS_MK_GETXYDBOPD(x, y, i, f, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" i, "str2" f, \
+ NULL, NSS_DBOP_##x##_##y, (e) }
+
+#define NSS_MK_GETXYDBOPCSTR(x, a, f, s, e) \
+ { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
+ "process_cstr", NSS_DBOP_##x##_##a, (e) }
+
+/*
+ * The getXbyY_to_dbop structure is hashed on first call in order to
+ * reduce the search time for the well known getXbyY operations.
+ * A binary search was not fast enough. There were on average
+ * 3-4 tests (strcmps) per getXbyY call.
+ *
+ * DBOP_PRIME_HASH must be a prime number (reasonably small) but that
+ * is sufficient to uniquely map the entries in the following table
+ * without collision.
+ *
+ * The DBOP_PRIME_HASH was selected as the smallest hash value
+ * for this table without collisions. Changing this table WILL
+ * necessitate re-testing for possible collisions.
+ */
+
+#define DBOP_PRIME_HASH 223
+#define DBOP_HASH_TAG 0xf0000000
+static int getXbyYdbopHASH[DBOP_PRIME_HASH] = { 0 };
+static mutex_t getXbydbop_hash_lock = DEFAULTMUTEX;
+static int getXbyYdbop_hashed = 0;
+
+static getXbyY_to_dbop_t getXbyY_to_dbop[] = {
+ /* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
+ NSS_MK_GETXYDBOPD(AUDITUSER, BYNAME, "auuser", "audituser", "n"),
+ NSS_MK_GETXYDBOP(AUTHATTR, BYNAME, "authattr", "n"),
+ /* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
+ NSS_MK_GETXYDBOP(BOOTPARAMS, BYNAME, "bootparams", "n"),
+ NSS_MK_GETXYDBOPC(ETHERS, HOSTTON, "ethers", "str2ether", "n"),
+ NSS_MK_GETXYDBOPC(ETHERS, NTOHOST, "ethers", "str2ether", "e"),
+ NSS_MK_GETXYDBOP(EXECATTR, BYNAME, "execattr", "A"),
+ NSS_MK_GETXYDBOP(EXECATTR, BYID, "execattr", "A"),
+ NSS_MK_GETXYDBOP(EXECATTR, BYNAMEID, "execattr", "A"),
+ NSS_MK_GETXYDBOP(GROUP, BYNAME, "group", "n"),
+ NSS_MK_GETXYDBOP(GROUP, BYGID, "group", "g"),
+ NSS_MK_GETXYDBOPCSTR(GROUP, BYMEMBER, "group", "str2group", "I"),
+ NSS_MK_GETXYDBOPC(HOSTS, BYNAME, "hosts", "str2hostent", "n"),
+ NSS_MK_GETXYDBOPC(HOSTS, BYADDR, "hosts", "str2hostent", "h"),
+ NSS_MK_GETXYDBOPC(IPNODES, BYNAME, "ipnodes", "str2hostent", "i"),
+ NSS_MK_GETXYDBOPC(IPNODES, BYADDR, "ipnodes", "str2hostent", "h"),
+ NSS_MK_GETXYDBOP(NETGROUP, IN, "netgroup", "t"),
+ NSS_MK_GETXYDBOP(NETGROUP, SET, "netgroup", "T"),
+ NSS_MK_GETXYDBOPC(NETMASKS, BYNET, "netmasks", "str2addr", "n"),
+ NSS_MK_GETXYDBOPC(NETWORKS, BYNAME, "net", "str2netent", "n"),
+ NSS_MK_GETXYDBOPC(NETWORKS, BYADDR, "net", "str2netent", "a"),
+ NSS_MK_GETXYDBOP(PASSWD, BYNAME, "passwd", "n"),
+ NSS_MK_GETXYDBOP(PASSWD, BYUID, "passwd", "u"),
+ NSS_MK_GETXYDBOP(PRINTERS, BYNAME, "printers", "n"),
+ NSS_MK_GETXYDBOP(PROFATTR, BYNAME, "profattr", "n"),
+ NSS_MK_GETXYDBOP(PROJECT, BYNAME, "project", "n"),
+ NSS_MK_GETXYDBOP(PROJECT, BYID, "project", "p"),
+ NSS_MK_GETXYDBOPC(PROTOCOLS, BYNAME, "proto", "str2protoent", "n"),
+ NSS_MK_GETXYDBOPC(PROTOCOLS, BYNUMBER, "proto", "str2protoent", "N"),
+ NSS_MK_GETXYDBOPA(PUBLICKEY, KEYS_BYNAME, "publickey", "k"),
+ NSS_MK_GETXYDBOPC(RPC, BYNAME, "rpc", "str2rpcent", "n"),
+ NSS_MK_GETXYDBOPC(RPC, BYNUMBER, "rpc", "str2rpcent", "N"),
+ NSS_MK_GETXYDBOPC(SERVICES, BYNAME, "services", "str2servent", "s"),
+ NSS_MK_GETXYDBOPC(SERVICES, BYPORT, "services", "str2servent", "S"),
+ NSS_MK_GETXYDBOPB(SHADOW, PASSWD, PASSWD_BYNAME, "shadow",
+ "str2spwd", "n"),
+ NSS_MK_GETXYDBOPC(TSOL_RH, BYADDR, "tsol_rh", "str_to_rhstr", "h"),
+ NSS_MK_GETXYDBOPC(TSOL_TP, BYNAME, "tsol_tp", "str_to_tpstr", "n"),
+ NSS_MK_GETXYDBOPC(TSOL_ZC, BYNAME, "tsol_zc", "str_to_zcstr", "n"),
+ NSS_MK_GETXYDBOP(USERATTR, BYNAME, "userattr", "n"),
+};
+
+static int
+nss_dbop_search(const char *name, uint32_t dbop)
+{
+ getXbyY_to_dbop_t *hptr;
+ int count = (sizeof (getXbyY_to_dbop) / sizeof (getXbyY_to_dbop_t));
+ uint32_t hval, g;
+ const char *cp;
+ int i, idx;
+
+ /* Uses a table size is known to have no collisions */
+ if (getXbyYdbop_hashed == 0) {
+ lmutex_lock(&getXbydbop_hash_lock);
+ if (getXbyYdbop_hashed == 0) {
+ for (i = 0; i < count; i++) {
+ cp = getXbyY_to_dbop[i].name;
+ hval = 0;
+ while (*cp) {
+ hval = (hval << 4) + *cp++;
+ if ((g = (hval & 0xf00000000)) != 0)
+ hval ^= g >> 24;
+ hval &= ~g;
+ }
+ hval += getXbyY_to_dbop[i].dbop;
+ hval %= DBOP_PRIME_HASH;
+ if (getXbyYdbopHASH[hval] != 0) {
+ /* hash table collision-see above */
+ lmutex_unlock(&getXbydbop_hash_lock);
+ return (-1);
+ }
+ getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
+ }
+ getXbyYdbop_hashed = 1;
+ }
+ lmutex_unlock(&getXbydbop_hash_lock);
+ }
+ cp = name;
+ hval = 0;
+ while (*cp) {
+ hval = (hval << 4) + *cp++;
+ if ((g = (hval & 0xf00000000)) != 0)
+ hval ^= g >> 24;
+ hval &= ~g;
+ }
+ hval += dbop;
+ hval %= DBOP_PRIME_HASH;
+ idx = getXbyYdbopHASH[hval];
+ if ((idx & DBOP_HASH_TAG) != DBOP_HASH_TAG)
+ return (-1);
+ idx &= ~DBOP_HASH_TAG;
+ if (idx >= count)
+ return (-1);
+ hptr = &getXbyY_to_dbop[idx];
+ if (hptr->dbop != dbop || strcmp(name, hptr->name) != 0)
+ return (-1);
+ return (idx);
+}
+
+/*
+ * nss_pack_key2str
+ * Private key to string packing function for getXbyY routines
+ * This routine performs a printf like parse over the argument
+ * key, given a string of items to pack and assembles the key in
+ * the packed structure. This routine is called (currently) by
+ * nss_default_key2str, but will be used by other external
+ * APIs in the future.
+ *
+ * buffer - Start of the key buffer location [in packed buffer]
+ * length - Length of key buffer component
+ * Key offsets are relative to start of key buffer location.
+ *
+ * Pack fields Key
+ * key.name n
+ * key.number N
+ * key.uid u
+ * key.gid g
+ * key.hostaddr h
+ * key.ipnode i
+ * key.projid p
+ * key.serv(name) s
+ * key.serv(port) S
+ * key.ether e
+ * key.pkey k
+ * key.netaddr a
+ * key.attrp A
+ * groupsbymember I
+ * innetgr_args t
+ * setnetgr_args T
+ */
+
+/*ARGSUSED*/
+static nss_status_t
+nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
+ const char *dbname, int dbop, size_t *rlen, const char *typestr)
+{
+ int i, j;
+ size_t len, len2, len3, len4, len5, slop;
+ nssuint_t *uptr, offv, offc;
+ struct nss_setnetgrent_args *sng;
+ struct nss_innetgr_args *ing;
+ struct nss_groupsbymem *gbm;
+ char **cv, *dptr;
+ nss_pnetgr_t *pptr;
+ _priv_execattr *pe;
+
+ if (buffer == NULL || length == 0 || arg == NULL ||
+ dbname == NULL || rlen == NULL || typestr == NULL)
+ return (NSS_ERROR);
+
+ while (typestr && *typestr) {
+ switch (*typestr++) {
+ case 'n':
+ if (arg->key.name == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(arg->key.name) + 1;
+ if (len >= length)
+ return (NSS_ERROR);
+ (void) strlcpy(buffer, arg->key.name, len);
+ *rlen = len;
+ break;
+ case 'N':
+ len = sizeof (nssuint_t);
+ if (len >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer = (nssuint_t)arg->key.number;
+ *rlen = len;
+ break;
+ case 'u':
+ len = sizeof (nssuint_t);
+ if (len >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer = (nssuint_t)arg->key.uid;
+ *rlen = len;
+ break;
+ case 'g':
+ len = sizeof (nssuint_t);
+ if (len >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer = (nssuint_t)arg->key.gid;
+ *rlen = len;
+ break;
+ case 'h':
+ if (arg->key.hostaddr.addr == NULL)
+ return (-1);
+ len = arg->key.hostaddr.len;
+ len = ROUND_UP(len, sizeof (nssuint_t));
+ len2 = (sizeof (nssuint_t) * 2) + len;
+ if (len2 >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer =
+ (nssuint_t)arg->key.hostaddr.len;
+ buffer = (void *)((char *)buffer + sizeof (nssuint_t));
+ *(nssuint_t *)buffer =
+ (nssuint_t)arg->key.hostaddr.type;
+ buffer = (void *)((char *)buffer + sizeof (nssuint_t));
+ (void) memcpy(buffer, arg->key.hostaddr.addr,
+ arg->key.hostaddr.len);
+ *rlen = len2;
+ break;
+ case 'i':
+ if (arg->key.ipnode.name == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(arg->key.ipnode.name) + 1;
+ len = ROUND_UP(len, sizeof (nssuint_t));
+ len2 = (sizeof (nssuint_t) * 2) + len;
+ if (len2 >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer =
+ (nssuint_t)arg->key.ipnode.af_family;
+ buffer = (void *)((char *)buffer + sizeof (nssuint_t));
+ *(nssuint_t *)buffer =
+ (nssuint_t)arg->key.ipnode.flags;
+ buffer = (void *)((char *)buffer + sizeof (nssuint_t));
+ (void) strlcpy(buffer, arg->key.ipnode.name, len);
+ *rlen = len2;
+ break;
+ case 'p':
+ len = sizeof (nssuint_t);
+ if (len >= length)
+ return (NSS_ERROR);
+ *(nssuint_t *)buffer = (nssuint_t)arg->key.projid;
+ *rlen = len;
+ break;
+ case 's':
+ if (arg->key.serv.serv.name == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(arg->key.serv.serv.name) + 1;
+ len2 = 1;
+ if (arg->key.serv.proto != NULL)
+ len2 += strlen(arg->key.serv.proto);
+ len3 = len + len2;
+ len3 = ROUND_UP(len3, sizeof (nssuint_t));
+ if (len3 >= length)
+ return (NSS_ERROR);
+ (void) strlcpy(buffer, arg->key.serv.serv.name, len);
+ buffer = (void *)((char *)buffer + len);
+ if (len2 > 1)
+ (void) strlcpy(buffer, arg->key.serv.proto,
+ len2);
+ else
+ *(char *)buffer = '\0';
+ *rlen = len3;
+ break;
+ case 'S':
+ len2 = 0;
+ if (arg->key.serv.proto != NULL)
+ len2 = strlen(arg->key.serv.proto) + 1;
+ len = sizeof (nssuint_t) + len2;
+ if (len >= length)
+ return (NSS_ERROR);
+ uptr = (nssuint_t *)buffer;
+ *uptr++ = (nssuint_t)arg->key.serv.serv.port;
+ if (len2) {
+ (void) strlcpy((char *)uptr,
+ arg->key.serv.proto, len2);
+ }
+ *rlen = len;
+ break;
+ case 'e':
+ if (arg->key.ether == NULL)
+ return (NSS_NOTFOUND);
+ len = sizeof (struct ether_addr);
+ len = ROUND_UP(len, sizeof (nssuint_t));
+ if (len >= length)
+ return (NSS_ERROR);
+ *(struct ether_addr *)buffer =
+ *(struct ether_addr *)arg->key.ether;
+ *rlen = len;
+ break;
+ case 'k':
+ if (arg->key.pkey.name == NULL ||
+ arg->key.pkey.keytype == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(arg->key.pkey.name) + 1;
+ len2 = strlen(arg->key.pkey.keytype) + 1;
+ len3 = len + len2;
+ len3 = ROUND_UP(len3, sizeof (nssuint_t));
+ if (len3 >= length)
+ return (NSS_ERROR);
+ (void) strlcpy(buffer, arg->key.pkey.name, len);
+ buffer = (void *)((char *)buffer + len);
+ (void) strlcpy(buffer, arg->key.pkey.keytype, len2);
+ *rlen = len3;
+ break;
+ case 'a':
+ uptr = (nssuint_t *)buffer;
+ len = sizeof (nssuint_t) * 2;
+ if (len >= length)
+ return (NSS_ERROR);
+ *uptr++ = (nssuint_t)arg->key.netaddr.net;
+ *uptr++ = (nssuint_t)arg->key.netaddr.type;
+ *rlen = len;
+ break;
+ case 'A':
+ pe = (_priv_execattr *)(arg->key.attrp);
+ if (pe == NULL)
+ return (NSS_NOTFOUND);
+ /* for search flag */
+ len = sizeof (nssuint_t);
+ /* for sizeof (_priv_execattr) static buffer */
+ /* Plus lots of slop just in case... */
+ slop = sizeof (nssuint_t) * 16;
+ len += slop;
+
+ len2 = len3 = len4 = len5 = 1;
+ if (pe->name != NULL)
+ len2 = strlen(pe->name) + 1;
+ if (pe->type != NULL)
+ len3 = strlen(pe->type) + 1;
+ if (pe->id != NULL)
+ len4 = strlen(pe->id) + 1;
+ if (pe->policy != NULL)
+ len5 = strlen(pe->policy) + 1;
+ /* head_exec, prev_exec - are client side only... */
+ len += len2 + len3 + len4 + len5;
+ len = ROUND_UP(len, sizeof (nssuint_t));
+ if (len >= length)
+ return (NSS_ERROR);
+ (void) memset((void *)buffer, 0, slop);
+ uptr = (nssuint_t *)((void *)((char *)buffer + slop));
+ *uptr++ = (nssuint_t)pe->search_flag;
+ dptr = (char *)uptr;
+ if (len2 == 1)
+ *dptr++ = '\0';
+ else {
+ (void) strlcpy(dptr, pe->name, len2);
+ dptr += len2;
+ }
+ if (len3 == 1)
+ *dptr++ = '\0';
+ else {
+ (void) strlcpy(dptr, pe->type, len3);
+ dptr += len3;
+ }
+ if (len4 == 1)
+ *dptr++ = '\0';
+ else {
+ (void) strlcpy(dptr, pe->id, len4);
+ dptr += len4;
+ }
+ if (len5 == 1)
+ *dptr++ = '\0';
+ else
+ (void) strlcpy(dptr, pe->policy, len5);
+ *rlen = len;
+ break;
+ case 'I':
+ gbm = (struct nss_groupsbymem *)arg;
+ if (gbm->username == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(gbm->username) + 1;
+ len2 = sizeof (nssuint_t) * 4;
+ len2 += ROUND_UP(len, sizeof (nssuint_t));
+ if (len2 >= length)
+ return (NSS_ERROR);
+ uptr = (nssuint_t *)buffer;
+ *uptr++ = (nssuint_t)gbm->force_slow_way;
+ *uptr++ = (nssuint_t)gbm->maxgids;
+ *uptr++ = (nssuint_t)gbm->numgids;
+ if (gbm->numgids == 1) {
+ *uptr++ = (nssuint_t)gbm->gid_array[0];
+ } else {
+ *uptr++ = (nssuint_t)0;
+ }
+ (void) strlcpy((void *)uptr, gbm->username, len);
+ *rlen = len2;
+ break;
+ case 't':
+ pptr = (nss_pnetgr_t *)buffer;
+ ing = (struct nss_innetgr_args *)arg;
+ len = sizeof (nss_pnetgr_t);
+ len2 = ing->arg[NSS_NETGR_MACHINE].argc +
+ ing->arg[NSS_NETGR_USER].argc +
+ ing->arg[NSS_NETGR_DOMAIN].argc +
+ ing->groups.argc;
+ len2 *= sizeof (nssuint_t);
+ len3 = 0;
+ for (j = 0; j < NSS_NETGR_N; j++) {
+ cv = ing->arg[j].argv;
+ for (i = ing->arg[j].argc; --i >= 0; ) {
+ if (*cv)
+ len3 += strlen(*cv++) + 1;
+ }
+ }
+ cv = ing->groups.argv;
+ for (i = ing->groups.argc; --i >= 0; ) {
+ if (*cv)
+ len3 += strlen(*cv++) + 1;
+ }
+ len3 = ROUND_UP(len3, sizeof (nssuint_t));
+ /*
+ * Double argv space. Reason:
+ * First 1/2 offsets
+ * Second 1/2 for client side pointer arrays
+ * resolves malloc/free issues with unpacked argvs
+ */
+ if ((len + (len2 << 1) + len3) >= length)
+ return (NSS_ERROR);
+ *rlen = len + (len2 << 1) + len3;
+
+ pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc;
+ pptr->user_argc = ing->arg[NSS_NETGR_USER].argc;
+ pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc;
+ pptr->groups_argc = ing->groups.argc;
+ offv = len;
+ uptr = (nssuint_t *)((void *)((char *)buffer + offv));
+ offc = len + (len2 << 1);
+ dptr = (char *)buffer + offc;
+ if (pptr->machine_argc == 0) {
+ pptr->machine_offv = (nssuint_t)0;
+ } else {
+ pptr->machine_offv = offv;
+ cv = ing->arg[NSS_NETGR_MACHINE].argv;
+ i = pptr->machine_argc;
+ offv += sizeof (nssuint_t) * i;
+ for (; --i >= 0; ) {
+ *uptr++ = offc;
+ len3 = strlen(*cv) + 1;
+ (void) strlcpy(dptr, *cv++, len3);
+ offc += len3;
+ dptr += len3;
+ }
+ }
+ if (pptr->user_argc == 0) {
+ pptr->user_offv = (nssuint_t)0;
+ } else {
+ pptr->user_offv = offv;
+ cv = ing->arg[NSS_NETGR_USER].argv;
+ i = pptr->user_argc;
+ offv += sizeof (nssuint_t) * i;
+ for (; --i >= 0; ) {
+ *uptr++ = offc;
+ len3 = strlen(*cv) + 1;
+ (void) strlcpy(dptr, *cv++, len3);
+ offc += len3;
+ dptr += len3;
+ }
+ }
+ if (pptr->domain_argc == 0) {
+ pptr->domain_offv = (nssuint_t)0;
+ } else {
+ pptr->domain_offv = offv;
+ cv = ing->arg[NSS_NETGR_DOMAIN].argv;
+ i = pptr->domain_argc;
+ offv += sizeof (nssuint_t) * i;
+ for (; --i >= 0; ) {
+ *uptr++ = offc;
+ len3 = strlen(*cv) + 1;
+ (void) strlcpy(dptr, *cv++, len3);
+ offc += len3;
+ dptr += len3;
+ }
+ }
+ if (pptr->groups_argc == 0) {
+ pptr->groups_offv = (nssuint_t)0;
+ } else {
+ pptr->groups_offv = offv;
+ cv = ing->groups.argv;
+ i = pptr->groups_argc;
+ offv += sizeof (nssuint_t) * i;
+ for (; --i >= 0; ) {
+ *uptr++ = offc;
+ len3 = strlen(*cv) + 1;
+ (void) strlcpy(dptr, *cv++, len3);
+ offc += len3;
+ dptr += len3;
+ }
+ }
+ break;
+ case 'T':
+ sng = (struct nss_setnetgrent_args *)arg;
+ if (sng->netgroup == NULL)
+ return (NSS_NOTFOUND);
+ len = strlen(sng->netgroup) + 1;
+ if (len >= length)
+ return (NSS_ERROR);
+ (void) strlcpy(buffer, sng->netgroup, len);
+ *rlen = len;
+ break;
+ default:
+ return (NSS_ERROR);
+ }
+ }
+ return (NSS_SUCCESS);
+}
+
+nss_status_t
+nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
+ const char *dbname, int dbop, size_t *rlen)
+{
+ int index;
+
+ if (buffer == NULL || length == 0 || arg == NULL ||
+ dbname == NULL || rlen == NULL)
+ return (NSS_ERROR);
+
+ /*
+ * If this is not one of the well known getXbyYs
+ * (IE _printers special processing etc.) use a
+ * local (non-nscd) getXbyY lookup.
+ */
+ if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0)
+ return (NSS_TRYLOCAL);
+
+ return (nss_pack_key2str(buffer, length, arg, dbname,
+ dbop, rlen, getXbyY_to_dbop[index].tostr));
+}
+
+/*ARGSUSED*/
+void
+nss_packed_set_status(void *buffer, size_t length, nss_status_t status,
+ nss_XbyY_args_t *arg)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_dbd_t *pdbd;
+ char *dbn;
+
+ /* sidestep odd cases */
+ pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
+ dbn = (char *)pdbd + pdbd->o_name;
+ if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) {
+ if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
+ struct nss_groupsbymem *in =
+ (struct nss_groupsbymem *)arg;
+
+ if (in->numgids >= 0) {
+ pbuf->p_status = NSS_SUCCESS;
+ pbuf->data_len = in->numgids *
+ sizeof (nssuint_t);
+ pbuf->p_herrno = 0;
+ } else {
+ pbuf->p_status = status;
+ pbuf->p_errno = errno;
+ pbuf->data_len = 0;
+ pbuf->p_herrno = (uint32_t)arg->h_errno;
+ }
+ return;
+ }
+ }
+ if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) {
+ if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
+ struct nss_innetgr_args *in =
+ (struct nss_innetgr_args *)arg;
+
+ /* tell nss_unpack() operation is successful */
+ pbuf->data_len = 1;
+
+ if (in->status == NSS_NETGR_FOUND) {
+ pbuf->p_status = NSS_SUCCESS;
+ } else {
+ pbuf->p_status = NSS_NOTFOUND;
+ pbuf->p_errno = errno;
+ }
+ return;
+ }
+ }
+
+ /* process normal cases */
+ if ((pbuf->p_status = status) != NSS_SUCCESS) {
+ if (arg->erange == 1)
+ pbuf->p_errno = ERANGE;
+ else
+ pbuf->p_errno = errno;
+ } else
+ pbuf->p_errno = 0;
+ if (arg != NULL) {
+ pbuf->p_herrno = (uint32_t)arg->h_errno;
+ pbuf->data_len = (nssuint_t)arg->returnlen;
+ } else {
+ pbuf->p_herrno = 0;
+ pbuf->data_len = 0;
+ }
+}
+
+/*
+ * nss_upack_key2arg
+ * Private string to key unpacking function for getXbyY routines
+ * This routine performs a scanf/printf like parse over the packed
+ * string, to uppack and re-assemble the key in the args structure.
+ *
+ * buffer - Start of the key buffer location [in packed buffer]
+ * length - Length of key buffer component
+ * Key offsets are relative to start of key buffer location.
+ *
+ * Unpack fields Key
+ * key.name n
+ * key.number N
+ * key.uid u
+ * key.gid g
+ * key.hostaddr h
+ * key.ipnode i
+ * key.projid p
+ * key.serv(name) s
+ * key.serv(port) S
+ * key.ether e
+ * key.pkey k
+ * key.netaddr a
+ * key.attrp A
+ * groupsbymember I
+ * innetgr_args t
+ * setnetgr_args T
+ * Assumes arguments are all valid
+ */
+
+/*ARGSUSED*/
+static nss_status_t
+nss_upack_key2arg(void *buffer, size_t length, char **dbname,
+ int *dbop, nss_XbyY_args_t *arg, int index)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ const char *strtype = NULL;
+ nssuint_t off, *uptr;
+ size_t len, slop;
+ int i, j;
+ char **cv, *bptr;
+ struct nss_setnetgrent_args *sng;
+ struct nss_innetgr_args *ing;
+ struct nss_groupsbymem *gbm;
+ nss_pnetgr_t *pptr;
+ _priv_execattr *pe;
+
+ off = pbuf->key_off;
+ bptr = (char *)buffer + off;
+ uptr = (nssuint_t *)((void *)bptr);
+ strtype = getXbyY_to_dbop[index].tostr;
+ if (strtype == NULL)
+ return (NSS_ERROR);
+ while (*strtype) {
+ switch (*strtype++) {
+ case 'n':
+ arg->key.name = (const char *)bptr;
+ break;
+ case 'N':
+ arg->key.number = (int)(*uptr);
+ break;
+ case 'u':
+ arg->key.uid = (uid_t)(*uptr);
+ break;
+ case 'g':
+ arg->key.gid = (gid_t)(*uptr);
+ break;
+ case 'h':
+ arg->key.hostaddr.len = (int)(*uptr++);
+ arg->key.hostaddr.type = (int)(*uptr++);
+ arg->key.hostaddr.addr = (const char *)uptr;
+ break;
+ case 'i':
+ arg->key.ipnode.af_family = (int)(*uptr++);
+ arg->key.ipnode.flags = (int)(*uptr++);
+ arg->key.ipnode.name = (const char *)uptr;
+ break;
+ case 'p':
+ arg->key.projid = (projid_t)(*uptr);
+ break;
+ case 's':
+ arg->key.serv.serv.name = (const char *)bptr;
+ len = strlen(arg->key.serv.serv.name) + 1;
+ bptr += len;
+ if (*(const char *)bptr == '\0')
+ arg->key.serv.proto = NULL;
+ else
+ arg->key.serv.proto = (const char *)bptr;
+ break;
+ case 'S':
+ arg->key.serv.serv.port = (int)(*uptr++);
+ if (pbuf->key_len == sizeof (nssuint_t)) {
+ arg->key.serv.proto = NULL;
+ } else {
+ bptr += sizeof (nssuint_t);
+ arg->key.serv.proto = (const char *)bptr;
+ }
+ break;
+ case 'e':
+ arg->key.ether = bptr;
+ break;
+ case 'k':
+ arg->key.pkey.name = (const char *)bptr;
+ len = strlen(arg->key.pkey.name) + 1;
+ bptr += len;
+ arg->key.pkey.keytype = (const char *)bptr;
+ break;
+ case 'a':
+ arg->key.netaddr.net = (uint32_t)(*uptr++);
+ arg->key.netaddr.type = (int)(*uptr++);
+ break;
+ case 'A':
+ pe = (_priv_execattr *)((void *)bptr);
+ /* use slop space as priv_execattr structure */
+ arg->key.attrp = (void *)pe;
+ /* skip over slop ... */
+ slop = sizeof (nssuint_t) * 16;
+ uptr = (nssuint_t *)((void *)((char *)bptr + slop));
+ pe->search_flag = (int)*uptr++;
+ bptr = (char *)uptr;
+ if (*bptr == '\0') {
+ pe->name = NULL;
+ bptr++;
+ } else {
+ pe->name = (char *)bptr;
+ bptr += strlen(pe->name) + 1;
+ }
+ if (*bptr == '\0') {
+ pe->type = NULL;
+ bptr++;
+ } else {
+ pe->type = (char *)bptr;
+ bptr += strlen(pe->type) + 1;
+ }
+ if (*bptr == '\0') {
+ pe->id = NULL;
+ bptr++;
+ } else {
+ pe->id = (char *)bptr;
+ bptr += strlen(pe->id) + 1;
+ }
+ if (*bptr == '\0') {
+ pe->policy = NULL;
+ } else {
+ pe->policy = (char *)bptr;
+ }
+ pe->head_exec = NULL;
+ pe->prev_exec = NULL;
+ break;
+ case 'I':
+ gbm = (struct nss_groupsbymem *)arg;
+ gbm->gid_array = (gid_t *)
+ ((void *)((char *)pbuf + pbuf->data_off));
+ gbm->force_slow_way = (int)(*uptr++);
+ gbm->maxgids = (int)(*uptr++);
+ gbm->numgids = (int)(*uptr++);
+ if (gbm->numgids == 1) {
+ /* insert initial group into data area */
+ ((nssuint_t *)
+ ((void *)gbm->gid_array))[0] = *uptr++;
+ }
+ gbm->username = (const char *)uptr;
+ break;
+ case 't':
+ pptr = (nss_pnetgr_t *)((void *)bptr);
+ ing = (struct nss_innetgr_args *)arg;
+ ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc;
+ ing->arg[NSS_NETGR_USER].argc = pptr->user_argc;
+ ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc;
+ ing->groups.argc = pptr->groups_argc;
+
+ /*
+ * Start of argv pointer storage
+ */
+ off = ing->arg[NSS_NETGR_MACHINE].argc +
+ ing->arg[NSS_NETGR_USER].argc +
+ ing->arg[NSS_NETGR_DOMAIN].argc +
+ ing->groups.argc;
+ off *= sizeof (nssuint_t);
+ off += sizeof (nss_pnetgr_t);
+
+ cv = (char **)((void *)(bptr + off));
+ uptr = (nssuint_t *)
+ ((void *)(bptr + sizeof (nss_pnetgr_t)));
+ for (j = 0; j < NSS_NETGR_N; j++) {
+ ing->arg[j].argv = cv;
+ for (i = 0; i < ing->arg[j].argc; i++) {
+ *cv++ = (bptr + *uptr++);
+ }
+ }
+ ing->groups.argv = cv;
+ for (i = 0; i < ing->groups.argc; i++) {
+ *cv++ = (bptr + *uptr++);
+ }
+ break;
+ case 'T':
+ sng = (struct nss_setnetgrent_args *)arg;
+ sng->netgroup = (const char *)bptr;
+ sng->iterator = 0;
+ break;
+
+ default:
+ return (NSS_ERROR);
+ }
+ }
+ return (NSS_SUCCESS);
+}
+
+static nss_status_t
+nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e)
+{
+ const char *name;
+ void *handle;
+ void *sym;
+
+ if ((handle = dlopen((const char *)0, RTLD_LAZY)) != NULL) {
+ if (initf) {
+ name = getXbyY_to_dbop[index].initfn;
+ if ((sym = dlsym(handle, name)) == 0) {
+ (void) dlclose(handle);
+ return (NSS_ERROR);
+ } else {
+ *initf = (nss_db_initf_t)sym;
+ }
+ }
+ if (s2e) {
+ name = getXbyY_to_dbop[index].strfn;
+ if ((sym = dlsym(handle, name)) == 0) {
+ (void) dlclose(handle);
+ return (NSS_ERROR);
+ } else {
+ *s2e = (nss_str2ent_t)sym;
+ }
+ }
+ }
+ return (NSS_SUCCESS);
+}
+
+nss_status_t
+nss_packed_getkey(void *buffer, size_t length, char **dbname,
+ int *dbop, nss_XbyY_args_t *arg)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_dbd_t *pdbd;
+ nssuint_t off;
+ int index;
+
+ if (buffer == NULL || length == 0 || dbop == NULL ||
+ arg == NULL || dbname == NULL)
+ return (NSS_ERROR);
+
+ *dbop = pbuf->nss_dbop;
+ off = pbuf->dbd_off;
+ pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
+ *dbname = (char *)buffer + off + pdbd->o_name;
+ if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0)
+ return (NSS_ERROR);
+ return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index));
+}
+
+
+/*
+ * str2packent: Standard format interposed str2X function for normal APIs
+ *
+ * Return values: 0 = success, 1 = parse error, 2 = erange ...
+ *
+ * The structure pointer is ignored since this is a nscd side packed request.
+ * The client side routine does all the real parsing; we just check limits and
+ * store the entry in the buffer we were passed by the caller.
+ */
+
+/*ARGSUSED*/
+static int
+str2packent(
+ const char *instr,
+ int lenstr,
+ void *ent, /* really (char *) */
+ char *buffer,
+ int buflen
+)
+{
+ if (buflen <= lenstr) { /* not enough buffer */
+ return (NSS_STR_PARSE_ERANGE);
+ }
+ (void) memmove(buffer, instr, lenstr);
+ buffer[lenstr] = '\0';
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
+
+/*
+ * getgroupsbymem format interposed cstr2X function
+ * This are similar to the API in getgrnam_r EXCEPT, this API
+ * store values in nssuint_t quantities in the buffer, not gid_t
+ * quantities. The unpacker in nss_common.c knows how to unpack
+ * into gid_t quantities.
+ */
+
+static nss_status_t
+pack_cstr(const char *instr, int instr_len, struct nss_groupsbymem *gbm)
+{
+ /*
+ * It's possible to do a much less inefficient version of this by
+ * selectively duplicating code from str2group(). For now,
+ * however, we'll take the easy way out and implement this on
+ * top of str2group().
+ */
+
+ const char *username = gbm->username;
+ nss_XbyY_buf_t *buf;
+ struct group *grp;
+ char **memp;
+ char *mem;
+ int parsestat;
+
+ /* TODO FIX THIS - with getdoorbsize type call */
+ buf = _nss_XbyY_buf_alloc(sizeof (struct group), NSS_BUFLEN_GROUP);
+ if (buf == 0)
+ return (NSS_UNAVAIL);
+
+ grp = (struct group *)buf->result;
+
+ parsestat = (*gbm->str2ent)(instr, instr_len,
+ grp, buf->buffer, buf->buflen);
+
+ if (parsestat != NSS_STR_PARSE_SUCCESS) {
+ _nss_XbyY_buf_free(buf);
+ return (NSS_NOTFOUND); /* === ? */
+ }
+
+ if (grp->gr_mem) {
+ for (memp = grp->gr_mem; (memp) && ((mem = *memp) != 0);
+ memp++) {
+ if (strcmp(mem, username) == 0) {
+ gid_t gid = grp->gr_gid;
+ nssuint_t *gidp;
+ int numgids;
+ int i;
+
+ gidp = (nssuint_t *)((void *)gbm->gid_array);
+ numgids = gbm->numgids;
+
+ _nss_XbyY_buf_free(buf);
+
+ for (i = 0; i < numgids &&
+ *gidp != (nssuint_t)gid;
+ i++, gidp++) {
+ ;
+ }
+ if (i >= numgids) {
+ if (i >= gbm->maxgids) {
+ /* Filled the array; stop searching */
+ return (NSS_SUCCESS);
+ }
+ *gidp = (nssuint_t)gid;
+ gbm->numgids = numgids + 1;
+ }
+ return (NSS_NOTFOUND); /* Explained in */
+ /* <nss_dbdefs.h> */
+ }
+ }
+ }
+ _nss_XbyY_buf_free(buf);
+ return (NSS_NOTFOUND);
+}
+
+/*
+ * Initialize db_root, initf, dbop and arg from a packed buffer
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root,
+ nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_str2ent_t s2e = str2packent;
+ nss_str2ent_t real_s2e = NULL;
+ nss_dbd_t *pdbd;
+ nssuint_t off;
+ char *dbname, *bptr;
+ size_t len;
+ int index;
+
+ if (buffer == NULL || length == 0 ||
+ dbop == NULL || arg == NULL)
+ return (NSS_ERROR);
+
+ /* init dbop */
+ *dbop = pbuf->nss_dbop;
+ off = pbuf->dbd_off;
+ pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
+ dbname = (char *)buffer + off + pdbd->o_name;
+ if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0)
+ return (NSS_ERROR);
+
+ /* db_root is initialized by nscd's based on door info */
+ /* do nothing here */
+
+ /* init key information - (and get dbname dbop etc...) */
+ if (nss_upack_key2arg(buffer, length, &dbname,
+ dbop, arg, index) != NSS_SUCCESS)
+ return (NSS_ERROR);
+
+ /* possible audituser init */
+ if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0)
+ arg->h_errno = (int)pbuf->p_herrno;
+
+ bptr = (char *)buffer + pbuf->data_off;
+ len = (size_t)pbuf->data_len;
+
+ /* sidestep odd arg cases */
+ if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
+ strcmp(dbname, NSS_DBNAM_GROUP) == 0) {
+ /* get initf and str2ent functions */
+ if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS)
+ return (NSS_ERROR);
+ ((struct nss_groupsbymem *)arg)->str2ent = real_s2e;
+ ((struct nss_groupsbymem *)arg)->process_cstr = pack_cstr;
+ return (NSS_SUCCESS);
+ }
+ if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN &&
+ strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) {
+ return (NSS_SUCCESS);
+ }
+
+ /* get initf and str2ent functions */
+ if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS)
+ return (NSS_ERROR);
+
+ /* init normal arg cases */
+ NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
+ arg->h_errno = 0;
+
+ return (NSS_SUCCESS);
+}
+
+/*
+ * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
+ */
+
+/*ARGSUSED*/
+nss_status_t
+nss_packed_context_init(void *buffer, size_t length, nss_db_root_t *db_root,
+ nss_db_initf_t *initf, nss_getent_t **contextp,
+ nss_XbyY_args_t *arg)
+{
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_str2ent_t s2e = str2packent;
+ char *bptr;
+ size_t len;
+
+ /* init arg */
+ if (arg != NULL) {
+ bptr = (char *)buffer + pbuf->data_off;
+ len = (size_t)pbuf->data_len;
+ NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
+ }
+
+ return (NSS_SUCCESS);
+}
diff --git a/usr/src/lib/libc/port/gen/nss_deffinder.c b/usr/src/lib/libc/port/gen/nss_deffinder.c
index dc06ff923b..7620512646 100644
--- a/usr/src/lib/libc/port/gen/nss_deffinder.c
+++ b/usr/src/lib/libc/port/gen/nss_deffinder.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -49,8 +48,14 @@
/* === ? move these constants to a public header file ? */
static const int dlopen_version = 1;
-static const char dlopen_format[] = "nss_%s.so.%d";
-static const char dlsym_format [] = "_nss_%s_%s_constr";
+#ifndef NSS_DLOPEN_FORMAT
+#define NSS_DLOPEN_FORMAT "nss_%s.so.%d"
+#endif
+#ifndef NSS_DLSYM_FORMAT
+#define NSS_DLSYM_FORMAT "_nss_%s_%s_constr"
+#endif
+static const char dlopen_format[] = NSS_DLOPEN_FORMAT;
+static const char dlsym_format [] = NSS_DLSYM_FORMAT;
static const size_t format_maxlen = sizeof (dlsym_format) - 4;
/*ARGSUSED*/
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 42b24ea43d..6d5cee49e7 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -1727,13 +1727,21 @@ SUNWprivate_1.1 {
_nrand48;
_nss_db_state_destr;
_nss_default_finders;
+ nss_default_key2str;
nss_delete;
_nss_delete;
nss_endent;
_nss_endent;
nss_getent;
_nss_getent;
+ _nss_initf_group;
_nss_initf_netgroup;
+ _nss_initf_passwd;
+ _nss_initf_shadow;
+ nss_packed_arg_init;
+ nss_packed_context_init;
+ nss_packed_getkey;
+ nss_packed_set_status;
nss_search;
_nss_search;
nss_setent;
@@ -2016,6 +2024,8 @@ SUNWprivate_1.1 {
_srand48;
_ssignal;
_statfs;
+ str2group;
+ str2passwd;
_str2sig;
str2spwd;
__strcoll_C;
diff --git a/usr/src/lib/libnsl/common/llib-lnsl b/usr/src/lib/libnsl/common/llib-lnsl
index 87f0091ba8..889d4bf1fa 100644
--- a/usr/src/lib/libnsl/common/llib-lnsl
+++ b/usr/src/lib/libnsl/common/llib-lnsl
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -24,7 +23,7 @@
/* PROTOLIB1 */
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1329,3 +1328,6 @@ bool_t xdr_ypdelete_args(XDR *xdrs, ypdelete_args *objp);
/* nis_sec_mechs.c */
char *__nis_keyalg2authtype(keylen_t keylen, algtype_t algtype,
char *authtype, size_t authtype_len);
+
+/* usr/src/lib/libnsl/nss/parse.c */
+char *_strtok_escape(char *string, char *sepset, char **lasts);
diff --git a/usr/src/lib/libnsl/key/publickey.c b/usr/src/lib/libnsl/key/publickey.c
index febc30e423..afea031537 100644
--- a/usr/src/lib/libnsl/key/publickey.c
+++ b/usr/src/lib/libnsl/key/publickey.c
@@ -124,6 +124,23 @@ static int extract_secret();
static DEFINE_NSS_DB_ROOT(db_root);
/*
+ * str2key
+ */
+/* ARGSUSED */
+static int
+str2key(const char *instr, int lenstr,
+ void *ent, char *buffer, int buflen) {
+ if (lenstr + 1 > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ /*
+ * We copy the input string into the output buffer
+ */
+ (void) memcpy(buffer, instr, lenstr);
+ buffer[lenstr] = '\0';
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
+/*
* These functions are the "backends" for the switch for public keys. They
* get both the public and private keys from each of the supported name
* services (nis, nisplus, files). They are passed the appropriate parameters
@@ -704,7 +721,7 @@ getkeys_ldap_g(
NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_PUBLICKEY);
- NSS_XbyY_INIT(&arg, buf->result, buf->buffer, buf->buflen, NULL);
+ NSS_XbyY_INIT(&arg, buf->result, buf->buffer, buf->buflen, str2key);
arg.key.pkey.name = netname;
/*
diff --git a/usr/src/lib/libnsl/nss/getauthattr.c b/usr/src/lib/libnsl/nss/getauthattr.c
index d734e99ab9..b01c7447e8 100644
--- a/usr/src/lib/libnsl/nss/getauthattr.c
+++ b/usr/src/lib/libnsl/nss/getauthattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -68,12 +67,12 @@ str2authattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
char *sep = KV_TOKEN_DELIMIT;
authstr_t *auth = (authstr_t *)ent;
- if ((instr >= buffer && (buffer + buflen) > instr) ||
- (buffer >= instr && (instr + lenstr) > buffer))
- return (NSS_STR_PARSE_PARSE);
if (lenstr >= buflen)
return (NSS_STR_PARSE_ERANGE);
- (void) strncpy(buffer, instr, buflen);
+
+ if (instr != buffer)
+ (void) strncpy(buffer, instr, buflen);
+
/*
* Remove newline that nis (yp_match) puts at the
* end of the entry it retrieves from the map.
@@ -81,6 +80,10 @@ str2authattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
if (buffer[lenstr] == '\n')
buffer[lenstr] = '\0';
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
+
auth->name = _strtok_escape(buffer, sep, &last);
auth->res1 = _strtok_escape(NULL, sep, &last);
auth->res2 = _strtok_escape(NULL, sep, &last);
diff --git a/usr/src/lib/libnsl/nss/getauuser.c b/usr/src/lib/libnsl/nss/getauuser.c
index 877a108ff8..f42b80cc5c 100644
--- a/usr/src/lib/libnsl/nss/getauuser.c
+++ b/usr/src/lib/libnsl/nss/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -72,12 +71,12 @@ str2auuser(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
char *sep = KV_TOKEN_DELIMIT;
au_user_str_t *au_user = (au_user_str_t *)ent;
- if ((instr >= buffer && (buffer + buflen) > instr) ||
- (buffer >= instr && (instr + lenstr) > buffer))
- return (NSS_STR_PARSE_PARSE);
if (lenstr >= buflen)
return (NSS_STR_PARSE_ERANGE);
- (void) strncpy(buffer, instr, buflen);
+
+ if (instr != buffer)
+ (void) strncpy(buffer, instr, buflen);
+
/*
* Remove newline that nis (yp_match) puts at the
* end of the entry it retrieves from the map.
@@ -86,6 +85,10 @@ str2auuser(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
buffer[lenstr] = '\0';
}
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
+
au_user->au_name = _strtok_escape(buffer, sep, &last);
au_user->au_always = _strtok_escape(NULL, sep, &last);
au_user->au_never = _strtok_escape(NULL, sep, &last);
diff --git a/usr/src/lib/libnsl/nss/getexecattr.c b/usr/src/lib/libnsl/nss/getexecattr.c
index 1990cea7ed..023667f092 100644
--- a/usr/src/lib/libnsl/nss/getexecattr.c
+++ b/usr/src/lib/libnsl/nss/getexecattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,15 +98,12 @@ str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
char *sep = KV_TOKEN_DELIMIT;
execstr_t *exec = (execstr_t *)ent;
- if (exec == NULL)
- return (NSS_STR_PARSE_PARSE);
-
- if ((instr >= buffer && (buffer + buflen) > instr) ||
- (buffer >= instr && (instr + lenstr) > buffer))
- return (NSS_STR_PARSE_PARSE);
if (lenstr >= buflen)
return (NSS_STR_PARSE_ERANGE);
- (void) strncpy(buffer, instr, buflen);
+
+ if (instr != buffer)
+ (void) strncpy(buffer, instr, buflen);
+
/*
* Remove newline that nis (yp_match) puts at the
* end of the entry it retrieves from the map.
@@ -116,6 +112,10 @@ str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
buffer[lenstr] = '\0';
}
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
+
exec->name = _strtok_escape(buffer, sep, &last);
exec->policy = _strtok_escape(NULL, sep, &last);
exec->type = _strtok_escape(NULL, sep, &last);
@@ -245,9 +245,12 @@ retry_policy:
res = nss_search(&pexec_root,
_nsw_initf_execattr, getby_flag,
&arg);
- _nss_db_state_destr(pexec_root.s);
+ if (pexec_root.s != NULL)
+ _nss_db_state_destr(
+ pexec_root.s);
}
- _nss_db_state_destr(prof_root.s);
+ if (prof_root.s != NULL)
+ _nss_db_state_destr(prof_root.s);
(void) mutex_unlock(&_nsw_exec_lock);
if ((pres == NSS_SUCCESS) || (conf == NULL))
break;
diff --git a/usr/src/lib/libnsl/nss/gethostby_door.c b/usr/src/lib/libnsl/nss/gethostby_door.c
index 8b7f66f46f..4c3bdebc38 100644
--- a/usr/src/lib/libnsl/nss/gethostby_door.c
+++ b/usr/src/lib/libnsl/nss/gethostby_door.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,7 +18,6 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -40,285 +38,20 @@
#ifdef PIC
-static struct hostent *process_gethost(struct hostent *, char *, int, int *,
- nsc_data_t *);
-
struct hostent *
_door_gethostbyname_r(const char *name, struct hostent *result, char *buffer,
int buflen, int *h_errnop)
{
-
- /*
- * allocate space on the stack for the nscd to return
- * host and host alias information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct hostent *resptr = NULL;
-
- if ((name == NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- adata = (sizeof (nsc_call_t) + strlen(name) + 1);
- ndata = sizeof (space);
- space.s_d.nsc_call.nsc_callnumber = GETHOSTBYNAME;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- if (h_errnop)
- *h_errnop = space.s_d.nsc_ret.nsc_errno;
- return (NULL);
- default:
- return ((struct hostent *)_switch_gethostbyname_r(name,
+ return ((struct hostent *)_switch_gethostbyname_r(name,
result, buffer, buflen, h_errnop));
- }
- resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
-
- /*
- * check if doors realloced buffer underneath of us....
- * munmap or suffer a memory leak
- */
-
- if (sptr != &space.s_d) {
- munmap((char *)sptr, ndata); /* return memory */
- }
-
- return (resptr);
}
struct hostent *
_door_gethostbyaddr_r(const char *addr, int length, int type,
struct hostent *result, char *buffer, int buflen, int *h_errnop)
{
- /*
- * allocate space on the stack for the nscd to return
- * host and host alias information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct hostent *resptr = NULL;
-
- if (addr == NULL) {
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- ndata = sizeof (space);
- adata = length + sizeof (nsc_call_t) + 1;
- sptr = &space.s_d;
-
- space.s_d.nsc_call.nsc_callnumber = GETHOSTBYADDR;
- space.s_d.nsc_call.nsc_u.addr.a_type = type;
- space.s_d.nsc_call.nsc_u.addr.a_length = length;
- (void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length);
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- if (h_errnop)
- *h_errnop = space.s_d.nsc_ret.nsc_errno;
- return (NULL);
- default:
- return ((struct hostent *)_switch_gethostbyaddr_r(addr,
+ return ((struct hostent *)_switch_gethostbyaddr_r(addr,
length, type, result, buffer, buflen, h_errnop));
- }
-
- resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
-
- /*
- * check if doors realloced buffer underneath of us....
- * munmap it or suffer a memory leak
- */
-
- if (sptr != &space.s_d) {
- munmap((char *)sptr, ndata); /* return memory */
- }
-
- return (resptr);
-
-}
-
-#if !defined(_LP64)
-
-static struct hostent *
-process_gethost(struct hostent *result, char *buffer, int buflen,
- int *h_errnop, nsc_data_t *sptr)
-{
- int i;
-
- char *fixed;
-
- fixed = (char *)(((int)buffer +3) & ~3);
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (buflen + sizeof (struct hostent)
- < sptr->nsc_ret.nsc_bufferbytesused) {
- /*
- * no enough space allocated by user
- */
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- (void) memcpy(buffer,
- sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent),
- sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent));
-
- sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer;
- sptr->nsc_ret.nsc_u.hst.h_aliases =
- (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer);
- sptr->nsc_ret.nsc_u.hst.h_addr_list =
- (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list +
- (int)buffer);
- for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) {
- sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer;
- }
- for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) {
- sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer;
- }
-
- *result = sptr->nsc_ret.nsc_u.hst;
-
- return (result);
}
-#else /* _LP64 */
-
-#define RNDUP(buf, n) (((uintptr_t)buf + n - 1l) & ~(n - 1l))
-
-static struct hostent *
-process_gethost(struct hostent *result, char *buffer, int buflen,
- int *h_errnop, nsc_data_t *sptr)
-{
- char *fixed;
- char *dest;
- char *start;
- char **aliaseslist;
- char **addrlist;
- int *alias;
- int *address;
- size_t strs;
- int numaliases;
- int numaddrs;
- int i;
-
- fixed = (char *)RNDUP(buffer, sizeof (char *));
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (buflen < 0) {
- /* no enough space allocated by user */
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- /* find out whether the user has provided sufficient space */
-
- start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
- strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
- alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
- for (numaliases = 0; alias[numaliases]; numaliases++)
- strs += 1 + strlen(start + alias[numaliases]);
- strs = RNDUP(strs, sizeof (int));
- strs += sizeof (char *) * (numaliases + 1);
- address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
- for (numaddrs = 0; address[numaddrs]; numaddrs++)
- strs += RNDUP(sptr->nsc_ret.nsc_u.hst.h_length, sizeof (int));
- strs += sizeof (char *) * (numaddrs + 1);
-
- if (buflen < strs) {
-
- /* no enough space allocated by user */
-
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
-
- /*
- * allocat the h_aliases list and the h_addr_list first to align 'em.
- */
-
- dest = buffer;
- aliaseslist = (char **)dest;
- dest += sizeof (char *) * (numaliases + 1);
- addrlist = (char **)dest;
- dest += sizeof (char *) * (numaddrs + 1);
-
- /* fill out h_name */
-
- start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
- (void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start);
- strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
- result->h_name = dest;
- dest += strs;
-
- /*
- * fill out the h_aliases list
- */
- for (i = 0; i < numaliases; i++) {
- alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
- (void) strcpy(dest, start + alias[i]);
- strs = 1 + strlen(start + alias[i]);
- aliaseslist[i] = dest;
- dest += strs;
- }
- aliaseslist[i] = 0; /* null term ptr chain */
-
- result->h_aliases = aliaseslist;
-
- /*
- * fill out the h_addr list
- */
-
- dest = (char *)RNDUP(dest, sizeof (int));
-
- for (i = 0; i < numaddrs; i++) {
- address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
- (void) memcpy(dest, start + address[i],
- sptr->nsc_ret.nsc_u.hst.h_length);
- strs = sptr->nsc_ret.nsc_u.hst.h_length;
- addrlist[i] = dest;
- dest += strs;
- dest = (char *)RNDUP(dest, sizeof (int));
- }
-
- addrlist[i] = 0; /* null term ptr chain */
-
- result->h_addr_list = addrlist;
-
- result->h_length = sptr->nsc_ret.nsc_u.hst.h_length;
- result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype;
-
- return (result);
-}
-#endif /* _LP64 */
#endif /* PIC */
diff --git a/usr/src/lib/libnsl/nss/gethostbyname_r.c b/usr/src/lib/libnsl/nss/gethostbyname_r.c
index 27435b95fe..7a3c5aaaa0 100644
--- a/usr/src/lib/libnsl/nss/gethostbyname_r.c
+++ b/usr/src/lib/libnsl/nss/gethostbyname_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -151,7 +150,10 @@ gethostbyaddr_r(const char *addr, int length, int type,
struct netconfig *nconf;
struct nss_netdirbyaddr_in nssin;
union nss_netdirbyaddr_out nssout;
- int neterr;
+ int neterr, dummy;
+
+ if (h_errnop == NULL)
+ h_errnop = &dummy;
if (type != AF_INET) {
*h_errnop = HOST_NOT_FOUND;
diff --git a/usr/src/lib/libnsl/nss/gethostent.c b/usr/src/lib/libnsl/nss/gethostent.c
index 8cbc3b9dec..c02c8c5ebf 100644
--- a/usr/src/lib/libnsl/nss/gethostent.c
+++ b/usr/src/lib/libnsl/nss/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
diff --git a/usr/src/lib/libnsl/nss/getipnodeby_door.c b/usr/src/lib/libnsl/nss/getipnodeby_door.c
index 8c0423196e..17e1f953c1 100644
--- a/usr/src/lib/libnsl/nss/getipnodeby_door.c
+++ b/usr/src/lib/libnsl/nss/getipnodeby_door.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,7 +18,6 @@
*
* CDDL HEADER END
*/
-
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -41,298 +39,20 @@
#ifdef PIC
-static struct hostent *__process_getipnode(struct hostent *, char *, int, int *,
- nsc_data_t *);
-
struct hostent *
_door_getipnodebyname_r(const char *name, struct hostent *result, char *buffer,
int buflen, int af_family, int flags, int *h_errnop)
{
-
- /*
- * allocate space on the stack for the nscd to return
- * host and host alias information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct hostent *resptr = NULL;
-
- if ((name == NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)
- - 2 * sizeof (int)))) {
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- adata = (sizeof (nsc_call_t) + strlen(name) + 1 + 2 * sizeof (int));
- ndata = sizeof (space);
- space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYNAME;
- space.s_d.nsc_call.nsc_u.ipnode.af_family = af_family;
- space.s_d.nsc_call.nsc_u.ipnode.flags = flags;
- (void) strcpy(space.s_d.nsc_call.nsc_u.ipnode.name, name);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- if (h_errnop)
- *h_errnop = space.s_d.nsc_ret.nsc_errno;
- return (NULL);
- default:
- return ((struct hostent *)_switch_getipnodebyname_r(name,
+ return ((struct hostent *)_switch_getipnodebyname_r(name,
result, buffer, buflen, af_family, flags, h_errnop));
- }
- resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr);
-
- /*
- * check if doors realloced buffer underneath of us....
- * munmap or suffer a memory leak
- */
-
- if (sptr != &space.s_d) {
- munmap((char *)sptr, ndata); /* return memory */
- }
-
- return (resptr);
}
struct hostent *
_door_getipnodebyaddr_r(const char *addr, int length, int type,
struct hostent *result, char *buffer, int buflen, int *h_errnop)
{
- /*
- * allocate space on the stack for the nscd to return
- * host and host alias information
- */
- union {
- nsc_data_t s_d;
- char s_b[8192];
- } space;
- nsc_data_t *sptr;
- int ndata;
- int adata;
- struct hostent *resptr = NULL;
-
- if (addr == NULL) {
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- ndata = sizeof (space);
- adata = length + sizeof (nsc_call_t) + 1;
- sptr = &space.s_d;
-
- space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYADDR;
- space.s_d.nsc_call.nsc_u.addr.a_type = type;
- space.s_d.nsc_call.nsc_u.addr.a_length = length;
- (void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length);
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- if (h_errnop)
- *h_errnop = space.s_d.nsc_ret.nsc_errno;
- return (NULL);
- default:
- return ((struct hostent *)_switch_getipnodebyaddr_r(addr,
+ return ((struct hostent *)_switch_getipnodebyaddr_r(addr,
length, type, result, buffer, buflen, h_errnop));
- }
-
- resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr);
-
- /*
- * check if doors realloced buffer underneath of us....
- * munmap it or suffer a memory leak
- */
-
- if (sptr != &space.s_d) {
- munmap((char *)sptr, ndata); /* return memory */
- }
-
- return (resptr);
-}
-
-#if !defined(_LP64)
-
-static struct hostent *
-__process_getipnode(struct hostent *result, char *buffer, int buflen,
- int *h_errnop, nsc_data_t *sptr)
-{
- int i;
-
- char *fixed;
-
- fixed = (char *)ROUND_UP((int)buffer, sizeof (char *));
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (buflen + sizeof (struct hostent)
- < sptr->nsc_ret.nsc_bufferbytesused) {
- /*
- * no enough space allocated by user
- */
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- (void) memcpy(buffer,
- sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent),
- sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent));
-
- sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer;
- sptr->nsc_ret.nsc_u.hst.h_aliases =
- (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer);
- sptr->nsc_ret.nsc_u.hst.h_addr_list =
- (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list +
- (int)buffer);
- for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) {
- sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer;
- }
- for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) {
- sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer;
- }
-
- *result = sptr->nsc_ret.nsc_u.hst;
-
- return (result);
-}
-
-#else /* _LP64 */
-
-static struct hostent *
-__process_getipnode(struct hostent *result, char *buffer, int buflen,
- int *h_errnop, nsc_data_t *sptr)
-{
- char *fixed;
- char *dest;
- char *start;
- char **aliaseslist;
- char **addrlist;
- int *alias;
- int *address;
- size_t strs;
- int numaliases;
- int numaddrs;
- int i;
-
- fixed = (char *)ROUND_UP(buffer, sizeof (char *));
- buflen -= fixed - buffer;
- buffer = fixed;
- if (buflen < 0) {
- /* no enough space allocated by user */
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- /*
- * find out whether the user has provided sufficient space
- */
- start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
- /*
- * Length of hostname + null
- */
- strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
- /*
- * length of all aliases + null
- */
- alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
- for (numaliases = 0; alias[numaliases]; numaliases++)
- strs += 1 + strlen(start + alias[numaliases]);
- /*
- * Realign on word boundary
- */
- strs = ROUND_UP(strs, sizeof (char *));
- /*
- * Count the array of pointers to all aliases + null pointer
- */
- strs += sizeof (char *) * (numaliases + 1);
- /*
- * length of all addresses + null. Also, account for word alignment.
- */
- address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
- for (numaddrs = 0; address[numaddrs]; numaddrs++) {
- strs += sptr->nsc_ret.nsc_u.hst.h_length;
- strs = ROUND_UP(strs, sizeof (char *));
- }
- /*
- * Count the array of pointers to all addresses + null pointer
- */
- strs += sizeof (char *) * (numaddrs + 1);
-
- if (buflen < strs) {
-
- /* no enough space allocated by user */
-
- errno = ERANGE;
- if (h_errnop)
- *h_errnop = HOST_NOT_FOUND;
- return (NULL);
- }
-
- /*
- * allocat the h_aliases list and the h_addr_list first to align 'em.
- */
- dest = buffer;
- aliaseslist = (char **)dest;
- dest += sizeof (char *) * (numaliases + 1);
- addrlist = (char **)dest;
- dest += sizeof (char *) * (numaddrs + 1);
- /*
- * fill out h_name
- */
- start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
- (void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start);
- strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
- result->h_name = dest;
- dest += strs;
- /*
- * fill out the h_aliases list
- */
- alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
- for (i = 0; i < numaliases; i++) {
- (void) strcpy(dest, start + alias[i]);
- aliaseslist[i] = dest;
- dest += 1 + strlen(start + alias[i]);
- }
- aliaseslist[i] = 0; /* null term ptr chain */
- result->h_aliases = aliaseslist;
-
- /*
- * fill out the h_addr list
- */
- dest = (char *)ROUND_UP(dest, sizeof (char *));
- address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
- for (i = 0; i < numaddrs; i++) {
- (void) memcpy(dest, start + address[i],
- sptr->nsc_ret.nsc_u.hst.h_length);
- addrlist[i] = dest;
- dest += sptr->nsc_ret.nsc_u.hst.h_length;
- dest = (char *)ROUND_UP(dest, sizeof (char *));
- }
-
- addrlist[i] = 0; /* null term ptr chain */
-
- result->h_addr_list = addrlist;
-
- result->h_length = sptr->nsc_ret.nsc_u.hst.h_length;
- result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype;
-
- return (result);
}
-#endif /* _LP64 */
#endif /* PIC */
diff --git a/usr/src/lib/libnsl/nss/getprofattr.c b/usr/src/lib/libnsl/nss/getprofattr.c
index ffda122e05..bf5f7e94fa 100644
--- a/usr/src/lib/libnsl/nss/getprofattr.c
+++ b/usr/src/lib/libnsl/nss/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -67,12 +66,11 @@ str2profattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
char *sep = KV_TOKEN_DELIMIT;
profstr_t *prof = (profstr_t *)ent;
- if ((instr >= buffer && (buffer + buflen) > instr) ||
- (buffer >= instr && (instr + lenstr) > buffer))
- return (NSS_STR_PARSE_PARSE);
if (lenstr >= buflen)
return (NSS_STR_PARSE_ERANGE);
- (void) strncpy(buffer, instr, buflen);
+ if (instr != buffer)
+ (void) strncpy(buffer, instr, buflen);
+
/*
* Remove newline that nis (yp_match) puts at the
* end of the entry it retrieves from the map.
@@ -80,6 +78,10 @@ str2profattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
if (buffer[lenstr] == '\n')
buffer[lenstr] = '\0';
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
+
prof->name = _strtok_escape(buffer, sep, &last);
prof->res1 = _strtok_escape(NULL, sep, &last);
prof->res2 = _strtok_escape(NULL, sep, &last);
diff --git a/usr/src/lib/libnsl/nss/getrpcent_r.c b/usr/src/lib/libnsl/nss/getrpcent_r.c
index 206b3896d0..e794ee7538 100644
--- a/usr/src/lib/libnsl/nss/getrpcent_r.c
+++ b/usr/src/lib/libnsl/nss/getrpcent_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -59,6 +58,10 @@ getrpcbyname_r(const char *name, struct rpcent *result, char *buffer,
nss_XbyY_args_t arg;
nss_status_t res;
+ if (name == (const char *)NULL) {
+ errno = ERANGE;
+ return (NULL);
+ }
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2rpcent);
arg.key.name = name;
arg.stayopen = rpc_stayopen;
diff --git a/usr/src/lib/libnsl/nss/getuserattr.c b/usr/src/lib/libnsl/nss/getuserattr.c
index 30b196c8de..5106155854 100644
--- a/usr/src/lib/libnsl/nss/getuserattr.c
+++ b/usr/src/lib/libnsl/nss/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -75,12 +74,12 @@ str2userattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
char *sep = KV_TOKEN_DELIMIT;
userstr_t *user = (userstr_t *)ent;
- if ((instr >= buffer && (buffer + buflen) > instr) ||
- (buffer >= instr && (instr + lenstr) > buffer))
- return (NSS_STR_PARSE_PARSE);
if (lenstr >= buflen)
return (NSS_STR_PARSE_ERANGE);
- (void) strncpy(buffer, instr, buflen);
+
+ if (instr != buffer)
+ (void) strncpy(buffer, instr, buflen);
+
/*
* Remove newline that nis (yp_match) puts at the
* end of the entry it retrieves from the map.
@@ -89,6 +88,10 @@ str2userattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
buffer[lenstr] = '\0';
}
+ /* quick exit do not entry fill if not needed */
+ if (ent == (void *)NULL)
+ return (NSS_STR_PARSE_SUCCESS);
+
user->name = _strtok_escape(buffer, sep, &last);
user->qualifier = _strtok_escape(NULL, sep, &last);
user->res1 = _strtok_escape(NULL, sep, &last);
diff --git a/usr/src/lib/libnsl/nss/netdir_inet.c b/usr/src/lib/libnsl/nss/netdir_inet.c
index a8fc687daf..411f24c63c 100644
--- a/usr/src/lib/libnsl/nss/netdir_inet.c
+++ b/usr/src/lib/libnsl/nss/netdir_inet.c
@@ -90,17 +90,10 @@
#define UDPDEV "/dev/udp"
#define UDP6DEV "/dev/udp6"
-#ifdef PIC
-#define DOOR_GETHOSTBYNAME_R _door_gethostbyname_r
-#define DOOR_GETHOSTBYADDR_R _door_gethostbyaddr_r
-#define DOOR_GETIPNODEBYNAME_R _door_getipnodebyname_r
-#define DOOR_GETIPNODEBYADDR_R _door_getipnodebyaddr_r
-#else
#define DOOR_GETHOSTBYNAME_R _switch_gethostbyname_r
#define DOOR_GETHOSTBYADDR_R _switch_gethostbyaddr_r
#define DOOR_GETIPNODEBYNAME_R _switch_getipnodebyname_r
#define DOOR_GETIPNODEBYADDR_R _switch_getipnodebyaddr_r
-#endif /* PIC */
#define DONT_SORT "SORT_ADDRS=NO"
#define DONT_SORT2 "SORT_ADDRS=FALSE"
diff --git a/usr/src/lib/libsecdb/common/getexecattr.c b/usr/src/lib/libsecdb/common/getexecattr.c
index 1f6782b84f..1e1ab20ffd 100644
--- a/usr/src/lib/libsecdb/common/getexecattr.c
+++ b/usr/src/lib/libsecdb/common/getexecattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -54,7 +53,6 @@ extern char *_strdup_null(char *);
static execattr_t *userprof(const char *, const char *, const char *, int);
static execattr_t *get_tail(execattr_t *);
static execattr_t *execstr2attr(execstr_t *);
-static execstr_t *process_getexec(execstr_t *, char *, int, nsc_data_t *);
execattr_t *
getexecattr()
@@ -73,26 +71,16 @@ getexecattr()
execattr_t *
getexecprof(const char *name, const char *type, const char *id, int search_flag)
{
- int len_unique;
int err = 0;
- int ndata = 0;
- int adata = 0;
char unique[NSS_BUFLEN_EXECATTR];
char buf[NSS_BUFLEN_EXECATTR];
execattr_t *head = (execattr_t *)NULL;
execattr_t *prev = (execattr_t *)NULL;
execstr_t exec;
execstr_t *tmp;
- execstr_t *resptr = (execstr_t *)NULL;
- nsc_data_t *sptr = (nsc_data_t *)NULL;
- union {
- nsc_data_t s_d;
- char s_b[NSS_BUFLEN_EXECATTR];
- } space;
(void) memset(unique, 0, NSS_BUFLEN_EXECATTR);
(void) memset(&exec, 0, sizeof (execstr_t));
- (void) memset(&space, 0, sizeof (space));
if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) {
return ((execattr_t *)NULL);
@@ -120,55 +108,6 @@ getexecprof(const char *name, const char *type, const char *id, int search_flag)
return (head);
}
-#ifdef PIC
- /*
- * If the search criteria is completely specified
- * and we only want a single entry,
- * then attempt to look up the entry using the nscd.
- * Only commands are cached.
- */
- if (name && type && (strcmp(type, KV_COMMAND) == 0) && id &&
- (search_flag == GET_ONE)) {
- if (snprintf(unique, NSS_BUFLEN_EXECATTR, "%s:%s:%s",
- name, type, id) >= NSS_BUFLEN_EXECATTR) {
- errno = ERANGE;
- return ((execattr_t *)NULL);
- }
- len_unique = strlen(unique);
- if ((len_unique >= (sizeof (space) - sizeof (nsc_data_t)))) {
- errno = ERANGE;
- return ((execattr_t *)NULL);
- }
- ndata = sizeof (space);
- adata = len_unique + sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETEXECID;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, unique);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- return ((execattr_t *)NULL);
- default:
- resptr = _getexecprof(name, type, id, search_flag,
- &exec, buf, NSS_BUFLEN_EXECATTR, &err);
- return (execstr2attr(resptr));
- }
- resptr = process_getexec(&exec, buf, NSS_BUFLEN_EXECATTR,
- sptr);
-
- /*
- * check if doors reallocated the memory underneath us
- * if they did munmap it or suffer a memory leak
- */
- if (sptr != &space.s_d)
- (void) munmap((void *)sptr, ndata);
-
- return (execstr2attr(resptr));
- } /* end if (name && type && id && search_flag == GET_ONE) */
-#endif /* PIC */
-
tmp = _getexecprof(name,
type,
id,
@@ -427,76 +366,6 @@ execstr2attr(execstr_t *es)
return (newexec);
}
-
-static execstr_t *
-process_getexec(
- execstr_t *result,
- char *buffer,
- int buflen,
- nsc_data_t *sptr)
-{
- char *fixed;
-#ifdef _LP64
- execstr_t exec64;
-
- fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
-#else
- fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
-#endif
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (sptr->nsc_ret.nsc_return_code != SUCCESS)
- return ((execstr_t *)NULL);
-
-#ifdef _LP64
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr32_t)
- > buflen)
-#else
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr_t)
- > buflen)
-#endif
- {
- errno = ERANGE;
- return ((execstr_t *)NULL);
- }
-
-#ifdef _LP64
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr32_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr32_t)));
- exec64.name = (char *)(sptr->nsc_ret.nsc_u.exec.name +
- (uintptr_t)buffer);
- exec64.type = (char *)(sptr->nsc_ret.nsc_u.exec.type +
- (uintptr_t)buffer);
- exec64.policy = (char *)(sptr->nsc_ret.nsc_u.exec.policy +
- (uintptr_t)buffer);
- exec64.res1 = (char *)(sptr->nsc_ret.nsc_u.exec.res1 +
- (uintptr_t)buffer);
- exec64.res2 = (char *)(sptr->nsc_ret.nsc_u.exec.res2 +
- (uintptr_t)buffer);
- exec64.id = (char *)(sptr->nsc_ret.nsc_u.exec.id +
- (uintptr_t)buffer);
- exec64.attr = (char *)(sptr->nsc_ret.nsc_u.exec.attr +
- (uintptr_t)buffer);
- exec64.next = (execstr_t *)NULL;
- *result = exec64;
-#else
- sptr->nsc_ret.nsc_u.exec.name += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.type += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.policy += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.res1 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.res2 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.id += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.attr += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.exec.next = (execstr_t *)NULL;
- *result = sptr->nsc_ret.nsc_u.exec;
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr_t)));
-#endif
- return (result);
-}
-
-
#ifdef DEBUG
void
print_execattr(execattr_t *exec)
diff --git a/usr/src/lib/libsecdb/common/getprofattr.c b/usr/src/lib/libsecdb/common/getprofattr.c
index ade2cdfcc8..bb3173672c 100644
--- a/usr/src/lib/libsecdb/common/getprofattr.c
+++ b/usr/src/lib/libsecdb/common/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -43,8 +42,6 @@ extern void _setprofattr(void);
extern void _endprofattr(void);
static profattr_t *profstr2attr(profstr_t *);
-static profstr_t *process_getprof(profstr_t *, char *, int, nsc_data_t *);
-
profattr_t *
getprofattr()
@@ -63,55 +60,13 @@ profattr_t *
getprofnam(const char *name)
{
int err = 0;
- int ndata = 0;
- int adata = 0;
char buf[NSS_BUFLEN_PROFATTR];
profstr_t prof;
- union {
- nsc_data_t s_d;
- char s_b[1024];
- } space;
- nsc_data_t *sptr = (nsc_data_t *)NULL;
profstr_t *resptr = (profstr_t *)NULL;
(void) memset(&prof, 0, sizeof (profstr_t));
-#ifdef PIC
- (void) memset(&space, 0, sizeof (space));
-
- if ((name == NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
- errno = ERANGE;
- return ((profattr_t *)NULL);
- }
- ndata = sizeof (space);
- adata = strlen(name) + sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETPROFNAM;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- return ((profattr_t *)NULL);
- default:
- (void) memset(&prof, 0, sizeof (profattr_t));
- resptr = _getprofnam(name, &prof, buf,
- NSS_BUFLEN_PROFATTR, &err);
- return (profstr2attr(resptr));
- }
- resptr = process_getprof(&prof, buf, NSS_BUFLEN_PROFATTR, sptr);
-
- /*
- * check if doors reallocated the memory underneath us
- * if they did munmap it or suffer a memory leak
- */
- if (sptr != &space.s_d)
- (void) munmap((void *)sptr, ndata);
-#else /* !PIC */
resptr = _getprofnam(name, &prof, buf, NSS_BUFLEN_PROFATTR, &err);
-#endif /* PIC */
return (profstr2attr(resptr));
@@ -166,67 +121,6 @@ profstr2attr(profstr_t *prof)
}
-static profstr_t *
-process_getprof(
- profstr_t *result,
- char *buffer,
- int buflen,
- nsc_data_t *sptr)
-{
- char *fixed;
-#ifdef _LP64
- profstr_t prof64;
-
- fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
-#else
- fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
-#endif
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (sptr->nsc_ret.nsc_return_code != SUCCESS)
- return ((profstr_t *)NULL);
-
-#ifdef _LP64
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (profstr32_t)
- > buflen)
-#else
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (profstr_t)
- > buflen)
-#endif
- {
- errno = ERANGE;
- return ((profstr_t *)NULL);
- }
-
-#ifdef _LP64
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (profstr32_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (profstr32_t)));
- prof64.name = (char *)(sptr->nsc_ret.nsc_u.prof.name +
- (uintptr_t)buffer);
- prof64.res1 = (char *)(sptr->nsc_ret.nsc_u.prof.res1 +
- (uintptr_t)buffer);
- prof64.res2 = (char *)(sptr->nsc_ret.nsc_u.prof.res2 +
- (uintptr_t)buffer);
- prof64.desc = (char *)(sptr->nsc_ret.nsc_u.prof.desc +
- (uintptr_t)buffer);
- prof64.attr = (char *)(sptr->nsc_ret.nsc_u.prof.attr +
- (uintptr_t)buffer);
- *result = prof64;
-#else
- sptr->nsc_ret.nsc_u.prof.name += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.prof.res1 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.prof.res2 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.prof.desc += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.prof.attr += (uintptr_t)buffer;
- *result = sptr->nsc_ret.nsc_u.prof;
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (profstr_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (profstr_t)));
-#endif
- return (result);
-}
-
-
/*
* Given a profile name, gets the list of profiles found from
* the whole hierarchy, using the given profile as root
diff --git a/usr/src/lib/libsecdb/common/getuserattr.c b/usr/src/lib/libsecdb/common/getuserattr.c
index 7c0c8b9ff8..dd0789b5dd 100644
--- a/usr/src/lib/libsecdb/common/getuserattr.c
+++ b/usr/src/lib/libsecdb/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,7 +45,6 @@ extern void _enduserattr(void);
static userattr_t *userstr2attr(userstr_t *);
-static userstr_t *process_getuser(userstr_t *, char *, int, nsc_data_t *);
userattr_t *
@@ -80,51 +78,11 @@ userattr_t *
getusernam(const char *name)
{
int err = 0;
- int ndata;
- int adata;
char buf[NSS_BUFLEN_USERATTR];
userstr_t user;
- union {
- nsc_data_t s_d;
- char s_b[1024];
- } space;
- nsc_data_t *sptr;
userstr_t *resptr = (userstr_t *)NULL;
-#ifdef PIC
- if ((name == NULL) ||
- (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
- errno = ERANGE;
- return ((userattr_t *)NULL);
- }
- ndata = sizeof (space);
- adata = strlen(name) + sizeof (nsc_call_t) + 1;
- space.s_d.nsc_call.nsc_callnumber = GETUSERNAM;
- (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
- sptr = &space.s_d;
-
- switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
- case SUCCESS: /* positive cache hit */
- break;
- case NOTFOUND: /* negative cache hit */
- return ((userattr_t *)NULL);
- default:
- (void) memset(&user, 0, sizeof (userattr_t));
- resptr = _getusernam(name, &user, buf,
- NSS_BUFLEN_USERATTR, &err);
- return (userstr2attr(resptr));
- }
- resptr = process_getuser(&user, buf, NSS_BUFLEN_USERATTR, sptr);
-
- /*
- * check if doors reallocated the memory underneath us
- * if they did munmap it or suffer a memory leak
- */
- if (sptr != &space.s_d)
- (void) munmap((void *)sptr, ndata);
-#else /* !PIC */
resptr = _getusernam(name, &user, buf, NSS_BUFLEN_USERATTR, &err);
-#endif /* PIC */
return (userstr2attr(resptr));
@@ -191,67 +149,6 @@ userstr2attr(userstr_t *user)
}
-static userstr_t *
-process_getuser(
- userstr_t *result,
- char *buffer,
- int buflen,
- nsc_data_t *sptr)
-{
- char *fixed;
-#ifdef _LP64
- userstr_t user64;
-
- fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
-#else
- fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
-#endif
- buflen -= fixed - buffer;
- buffer = fixed;
-
- if (sptr->nsc_ret.nsc_return_code != SUCCESS)
- return ((userstr_t *)NULL);
-
-#ifdef _LP64
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (userstr32_t)
- > buflen)
-#else
- if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (userstr_t)
- > buflen)
-#endif
- {
- errno = ERANGE;
- return ((userstr_t *)NULL);
- }
-
-#ifdef _LP64
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (userstr32_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (userstr32_t)));
- user64.name = (char *)(sptr->nsc_ret.nsc_u.user.name +
- (uintptr_t)buffer);
- user64.qualifier = (char *)(sptr->nsc_ret.nsc_u.user.qualifier +
- (uintptr_t)buffer);
- user64.res1 = (char *)(sptr->nsc_ret.nsc_u.user.res1 +
- (uintptr_t)buffer);
- user64.res2 = (char *)(sptr->nsc_ret.nsc_u.user.res2 +
- (uintptr_t)buffer);
- user64.attr = (char *)(sptr->nsc_ret.nsc_u.user.attr +
- (uintptr_t)buffer);
- *result = user64;
-#else
- sptr->nsc_ret.nsc_u.user.name += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.user.qualifier += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.user.res1 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.user.res2 += (uintptr_t)buffer;
- sptr->nsc_ret.nsc_u.user.attr += (uintptr_t)buffer;
- *result = sptr->nsc_ret.nsc_u.user;
- (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (userstr_t)),
- (sptr->nsc_ret.nsc_bufferbytesused - sizeof (userstr_t)));
-#endif
- return (result);
-}
-
-
#ifdef DEBUG
void
print_userattr(userattr_t *user)
diff --git a/usr/src/lib/libsldap/Makefile.com b/usr/src/lib/libsldap/Makefile.com
index ce3a899fec..244c974085 100644
--- a/usr/src/lib/libsldap/Makefile.com
+++ b/usr/src/lib/libsldap/Makefile.com
@@ -22,8 +22,9 @@
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+#ident "%Z%%M% %I% %E% SMI"
#
+# lib/libsldap/Makefile.com
LIBRARY= libsldap.a
VERS= .1
@@ -32,7 +33,7 @@ SLDAPOBJ= ns_common.o ns_reads.o ns_writes.o \
ns_connect.o ns_config.o ns_error.o \
ns_cache_door.o ns_getalias.o ns_trace.o \
ns_init.o ns_crypt.o ns_confmgr.o \
- ns_mapping.o ns_wrapper.o
+ ns_mapping.o ns_wrapper.o ns_sasl.o
OBJECTS= $(SLDAPOBJ)
@@ -41,13 +42,14 @@ include ../../Makefile.lib
SRCS = $(SLDAPOBJ:%.o=../common/%.c)
LIBS = $(DYNLIB) $(LINTLIB)
$(LINTLIB):= SRCS=../common/llib-lsldap
-LDLIBS += -lnsl -lldap -lc
+LDLIBS += -lnsl -lldap -lscf -lc
SRCDIR = ../common
CFLAGS += $(CCVERBOSE)
-LOCFLAGS += -D_REENTRANT -DSUNW_OPTIONS -DTHREAD_SUNOS5_LWP
-CPPFLAGS += -I../common -I$(SRC)/lib/libldap5/include/ldap -I/usr/include/mps $(LOCFLAGS)
+LOCFLAGS += -D_REENTRANT -DSUNW_OPTIONS
+CPPFLAGS += -I../common -I$(SRC)/lib/libldap5/include/ldap \
+ -I/usr/include/mps $(LOCFLAGS)
LINTFLAGS += -erroff=E_BAD_PTR_CAST_ALIGN
LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN
diff --git a/usr/src/lib/libsldap/common/llib-lsldap b/usr/src/lib/libsldap/common/llib-lsldap
index 6114809d89..466116a856 100644
--- a/usr/src/lib/libsldap/common/llib-lsldap
+++ b/usr/src/lib/libsldap/common/llib-lsldap
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -23,7 +22,7 @@
/* PROTOLIB1 */
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -186,3 +185,49 @@ char *__s_api_get_canonical_name(
ns_ldap_entry_t *entry,
ns_ldap_attr_t *attrptr,
int case_ignore);
+
+void __ns_ldap_setServer(
+ int set);
+
+ns_ldap_error_t *__ns_ldap_LoadConfiguration(
+ void);
+
+ns_ldap_error_t *__ns_ldap_DumpConfiguration(
+ char *file);
+
+ns_ldap_error_t *__ns_ldap_DumpLdif(
+ char *filename);
+
+ns_ldap_error_t *__ns_ldap_print_config(
+ int verbose);
+
+void __ns_ldap_default_config(
+ void);
+
+int __ns_ldap_download(
+ const char *profile,
+ char *addr,
+ char *baseDN,
+ ns_ldap_error_t **errorp);
+
+int __ns_ldap_check_dns_preq(
+ int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ const char *fname,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
+
+int __ns_ldap_check_gssapi_preq(
+ int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
+
+int __ns_ldap_check_all_preq(
+ int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
diff --git a/usr/src/lib/libsldap/common/mapfile-vers b/usr/src/lib/libsldap/common/mapfile-vers
index 37fd9dd2be..18a1ddd867 100644
--- a/usr/src/lib/libsldap/common/mapfile-vers
+++ b/usr/src/lib/libsldap/common/mapfile-vers
@@ -32,6 +32,12 @@ SUNWprivate_1.1 {
global:
__ns_ldap_getAcctMgmt;
__s_api_get_canonical_name;
+ __ns_ldap_getAttrStruct;
+ __ns_ldap_self_gssapi_config;
+ __ns_ldap_self_gssapi_only_set;
+ __ns_ldap_check_dns_preq;
+ __ns_ldap_check_gssapi_preq;
+ __ns_ldap_check_all_preq;
} SUNWprivate_1.0;
SUNWprivate_1.0 {
diff --git a/usr/src/lib/libsldap/common/ns_cache_door.h b/usr/src/lib/libsldap/common/ns_cache_door.h
index 21d32b5292..d6c9e3a56e 100644
--- a/usr/src/lib/libsldap/common/ns_cache_door.h
+++ b/usr/src/lib/libsldap/common/ns_cache_door.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -164,6 +163,8 @@ typedef union {
#define NS_CACHE_NORESP "1"
#define NS_CACHE_NEXT "2"
#define NS_CACHE_WRITE "3"
+#define NS_CACHE_ADDR_HOSTNAME "H"
+#define NS_CACHE_ADDR_IP "I"
/*
* GETCACHE/SETCACHE data flags
diff --git a/usr/src/lib/libsldap/common/ns_common.c b/usr/src/lib/libsldap/common/ns_common.c
index 2089509afc..1244b22710 100644
--- a/usr/src/lib/libsldap/common/ns_common.c
+++ b/usr/src/lib/libsldap/common/ns_common.c
@@ -2223,16 +2223,24 @@ __s_api_removeServer(const char *server)
(void) memset(ret, 0, sizeof (ns_server_info_t));
(void) memset(space.s_b, 0, DOORBUFFERSIZE);
- adata = (sizeof (ldap_call_t) + strlen(ireq) +1);
+ adata = (sizeof (ldap_call_t) + strlen(ireq) +
+ strlen(NS_CACHE_ADDR_IP) + 1);
adata += strlen(DOORLINESEP) + 1;
adata += strlen(server) + 1;
ndata = sizeof (space);
space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER;
len = sizeof (space) - sizeof (space.s_d.ldap_call.ldap_callnumber);
- (void) strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len);
- (void) strlcat(space.s_d.ldap_call.ldap_u.domainname, DOORLINESEP, len);
- (void) strlcat(space.s_d.ldap_call.ldap_u.domainname, server, len);
+ if (strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len) >= len)
+ return (-1);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname,
+ NS_CACHE_ADDR_IP, len) >= len)
+ return (-1);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname, DOORLINESEP, len) >=
+ len)
+ return (-1);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname, server, len) >= len)
+ return (-1);
sptr = &space.s_d;
/* try to remove the server via the door interface */
diff --git a/usr/src/lib/libsldap/common/ns_config.c b/usr/src/lib/libsldap/common/ns_config.c
index 1e52104c6c..fb24f7721b 100644
--- a/usr/src/lib/libsldap/common/ns_config.c
+++ b/usr/src/lib/libsldap/common/ns_config.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -140,6 +139,7 @@ static ns_enum_map ns_auth_enum_v2[] = {
{ ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_CONF),
"sasl/DIGEST-MD5:auth-conf" },
{ ENUM2INT(NS_LDAP_EA_SASL_EXTERNAL), "sasl/EXTERNAL" },
+ { ENUM2INT(NS_LDAP_EA_SASL_GSSAPI), "sasl/GSSAPI" },
{ ENUM2INT(NS_LDAP_EA_TLS_NONE), "tls:none" },
{ ENUM2INT(NS_LDAP_EA_TLS_SIMPLE), "tls:simple" },
{ ENUM2INT(NS_LDAP_EA_TLS_SASL_CRAM_MD5), "tls:sasl/CRAM-MD5" },
@@ -1005,7 +1005,7 @@ __s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn)
int i, len, cnt;
const char *begin;
char **ppc;
- int *pi;
+ int *pi, self, gssapi;
if (ptr == NULL)
@@ -1171,7 +1171,38 @@ __s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn)
}
ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm;
}
-
+ /*
+ * If credential level self is defined, there should be
+ * at least an auth method sasl/GSSAPI and vice versa.
+ */
+ self = 0;
+ cnt = ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_acnt;
+ for (i = 0; i < cnt; i++) {
+ if (ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_pi[i] ==
+ NS_LDAP_CRED_SELF)
+ self++;
+ }
+ gssapi = 0;
+ cnt = ptr->paramList[NS_LDAP_AUTH_P].ns_acnt;
+ for (i = 0; i < cnt; i++) {
+ if (ptr->paramList[NS_LDAP_AUTH_P].ns_pi[i] ==
+ NS_LDAP_EA_SASL_GSSAPI)
+ gssapi++;
+ }
+ if (gssapi == 0 && self > 0) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: "
+ "Credential level self requires "
+ "authentication method sasl/GSSAPI"));
+ return (NS_PARSE_ERR);
+ }
+ if (gssapi > 0 && self == 0) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: "
+ "Authentication method sasl/GSSAPI "
+ "requires credential level self"));
+ return (NS_PARSE_ERR);
+ }
return (NS_SUCCESS);
}
@@ -3453,6 +3484,12 @@ __s_api_AuthEnumtoStruct(const EnumAuthType_t i)
ap->type = NS_LDAP_AUTH_SASL;
ap->saslmech = NS_LDAP_SASL_EXTERNAL;
break;
+ case NS_LDAP_EA_SASL_GSSAPI:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_GSSAPI;
+ ap->saslopt = NS_LDAP_SASLOPT_INT |
+ NS_LDAP_SASLOPT_PRIV;
+ break;
case NS_LDAP_EA_TLS_NONE:
ap->type = NS_LDAP_AUTH_TLS;
ap->tlstype = NS_LDAP_TLS_NONE;
diff --git a/usr/src/lib/libsldap/common/ns_connect.c b/usr/src/lib/libsldap/common/ns_connect.c
index ccf75a9963..514c802b34 100644
--- a/usr/src/lib/libsldap/common/ns_connect.c
+++ b/usr/src/lib/libsldap/common/ns_connect.c
@@ -38,6 +38,7 @@
#include <nsswitch.h>
#include <nss_dbdefs.h>
#include "solaris-priv.h"
+#include "solaris-int.h"
#include "ns_sldap.h"
#include "ns_internal.h"
#include "ns_cache_door.h"
@@ -54,8 +55,18 @@ extern int ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip);
static int openConnection(LDAP **, const char *, const ns_cred_t *,
int, ns_ldap_error_t **, int, int);
-
-static mutex_t sessionPoolLock = DEFAULTMUTEX;
+/*
+ * sessionLock, wait4session, sessionTid
+ * are variables to synchronize the creation/retrieval of a connection.
+ * MTperCon is a flag to enable/disable multiple threads sharing the same
+ * connection.
+ * sessionPoolLock is a mutex lock for the connection pool.
+ */
+static mutex_t sessionLock = DEFAULTMUTEX;
+static int wait4session = 0;
+static thread_t sessionTid = 0;
+int MTperConn = 1;
+static rwlock_t sessionPoolLock = DEFAULTRWLOCK;
static Connection **sessionPool = NULL;
static int sessionPoolSize = 0;
@@ -65,10 +76,239 @@ static mutex_t nscdLock = DEFAULTMUTEX;
static int nscdChecked = 0;
static pid_t checkedPid = -1;
static int isNscd = 0;
+/*
+ * SSF values are for SASL integrity & privacy.
+ * JES DS5.2 does not support this feature but DS6 does.
+ * The values between 0 and 65535 can work with both server versions.
+ */
+#define MAX_SASL_SSF 65535
+#define MIN_SASL_SSF 0
/* Number of hostnames to allocate memory for */
#define NUMTOMALLOC 32
+/*
+ * ns_mtckey is for sharing a ldap connection among multiple
+ * threads; created by ns_ldap_init() in ns_init.c
+ */
+extern thread_key_t ns_mtckey;
+
+/* Per thread LDAP error resides in thread-specific data. */
+struct ldap_error {
+ int le_errno;
+ char *le_matched;
+ char *le_errmsg;
+};
+
+/* destructor */
+void
+ns_tsd_cleanup(void *key) {
+ struct ldap_error *le = (struct ldap_error *)key;
+
+ if (le == NULL)
+ return;
+ if (le->le_matched != NULL) {
+ ldap_memfree(le->le_matched);
+ }
+ if (le->le_errmsg != NULL) {
+ ldap_memfree(le->le_errmsg);
+ }
+ free(le);
+}
+
+/* Callback function for allocating a mutex */
+static void *
+ns_mutex_alloc(void)
+{
+ mutex_t *mutexp = NULL;
+
+ if ((mutexp = malloc(sizeof (mutex_t))) != NULL) {
+ if (mutex_init(mutexp, USYNC_THREAD, NULL) != 0) {
+ free(mutexp);
+ mutexp = NULL;
+ }
+ }
+ return (mutexp);
+}
+
+/* Callback function for freeing a mutex */
+static void
+ns_mutex_free(void *mutexp)
+{
+ (void) mutex_destroy((mutex_t *)mutexp);
+ free(mutexp);
+}
+
+/*
+ * Function for setting up thread-specific data
+ * where per thread LDAP error is stored
+ */
+static int
+tsd_setup()
+{
+ void *tsd;
+ int rc;
+
+ /* return success if TSD already set */
+ rc = thr_getspecific(ns_mtckey, &tsd);
+ if (rc == 0 && tsd != NULL)
+ return (0);
+
+ /* allocate and set TSD */
+ tsd = (void *) calloc(1, sizeof (struct ldap_error));
+ if (tsd == NULL)
+ return (-1);
+ rc = thr_setspecific(ns_mtckey, tsd);
+ if (rc != 0) { /* must be ENOMEM */
+ free(tsd);
+ return (-1);
+ }
+ return (0);
+
+
+}
+
+/* Callback function for setting the per thread LDAP error */
+/*ARGSUSED*/
+static void
+set_ld_error(int err, char *matched, char *errmsg, void *dummy)
+{
+ struct ldap_error *le;
+
+ if (thr_getspecific(ns_mtckey, (void **)&le) != 0) {
+ syslog(LOG_ERR, "set_ld_error: thr_getspecific failed. errno"
+ " %d", errno);
+ return;
+ }
+ le->le_errno = err;
+ if (le->le_matched != NULL) {
+ ldap_memfree(le->le_matched);
+ }
+ le->le_matched = matched;
+ if (le->le_errmsg != NULL) {
+ ldap_memfree(le->le_errmsg);
+ }
+ le->le_errmsg = errmsg;
+}
+/* Callback function for getting the per thread LDAP error */
+/*ARGSUSED*/
+static int
+get_ld_error(char **matched, char **errmsg, void *dummy)
+{
+ struct ldap_error *le;
+
+ if (thr_getspecific(ns_mtckey, (void **)&le) != 0) {
+ syslog(LOG_ERR, "get_ld_error: thr_getspecific failed. errno"
+ " %d", errno);
+ return (errno);
+ }
+ if (matched != NULL) {
+ *matched = le->le_matched;
+ }
+ if (errmsg != NULL) {
+ *errmsg = le->le_errmsg;
+ }
+ return (le->le_errno);
+}
+
+/* Callback function for setting per thread errno */
+static void
+set_errno(int err)
+{
+ errno = err;
+}
+
+/* Callback function for getting per thread errno */
+static int
+get_errno(void)
+{
+ return (errno);
+}
+
+/*
+ * set up to allow multiple threads to use the same ldap connection
+ */
+static int
+setup_mt_conn(LDAP *ld)
+{
+
+ struct ldap_thread_fns tfns;
+ struct ldap_extra_thread_fns extrafns;
+ int rc;
+
+ /*
+ * Set the function pointers for dealing with mutexes
+ * and error information
+ */
+ (void) memset(&tfns, '\0', sizeof (struct ldap_thread_fns));
+ tfns.ltf_mutex_alloc = (void *(*)(void)) ns_mutex_alloc;
+ tfns.ltf_mutex_free = (void (*)(void *)) ns_mutex_free;
+ tfns.ltf_mutex_lock = (int (*)(void *)) mutex_lock;
+ tfns.ltf_mutex_unlock = (int (*)(void *)) mutex_unlock;
+ tfns.ltf_get_errno = get_errno;
+ tfns.ltf_set_errno = set_errno;
+ tfns.ltf_get_lderrno = get_ld_error;
+ tfns.ltf_set_lderrno = set_ld_error;
+ tfns.ltf_lderrno_arg = NULL;
+
+ /*
+ * Set up this session to use those function pointers
+ */
+ rc = ldap_set_option(ld, LDAP_OPT_THREAD_FN_PTRS,
+ (void *) &tfns);
+ if (rc < 0) {
+ syslog(LOG_WARNING, "libsldap: ldap_set_option "
+ "(LDAP_OPT_THREAD_FN_PTRS)");
+ return (-1);
+ }
+
+ /*
+ * Set the function pointers for working with semaphores
+ */
+ (void) memset(&extrafns, '\0',
+ sizeof (struct ldap_extra_thread_fns));
+ extrafns.ltf_threadid_fn = (void * (*)(void))thr_self;
+ extrafns.ltf_mutex_trylock = NULL;
+ extrafns.ltf_sema_alloc = NULL;
+ extrafns.ltf_sema_free = NULL;
+ extrafns.ltf_sema_wait = NULL;
+ extrafns.ltf_sema_post = NULL;
+
+ /* Set up this session to use those function pointers */
+ rc = ldap_set_option(ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS,
+ (void *) &extrafns);
+ if (rc < 0) {
+ syslog(LOG_WARNING, "libsldap: ldap_set_option "
+ "(LDAP_OPT_EXTRA_THREAD_FN_PTRS)");
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+ns_setup_mt_conn_and_tsd(LDAP *ld) {
+ thread_t t = thr_self();
+ void *tsd;
+ /* set up to share this connection among threads */
+ if (MTperConn == 1) {
+ if (tsd_setup() == -1) {
+ syslog(LOG_ERR, "tid= %d: unable "
+ "to set up TSD\n", t);
+ } else {
+ if (setup_mt_conn(ld) == -1) {
+ /* multiple threads per connection not supported */
+ syslog(LOG_ERR, "tid= %d: multiple "
+ "threads per connection not "
+ "supported\n", t);
+ (void) thr_getspecific(ns_mtckey, &tsd);
+ ns_tsd_cleanup(tsd);
+ (void) thr_setspecific(ns_mtckey, NULL);
+ MTperConn = 0;
+ }
+ }
+ }
+}
/*
* Check /proc/PID/psinfo to see if this process is nscd
@@ -126,7 +366,7 @@ nscd_proc()
static int
__s_api_requestServer(const char *request, const char *server,
- ns_server_info_t *ret, ns_ldap_error_t **error)
+ ns_server_info_t *ret, ns_ldap_error_t **error, const char *addrType)
{
union {
ldap_data_t s_d;
@@ -142,7 +382,7 @@ __s_api_requestServer(const char *request, const char *server,
char **mptr, **mptr1, **cptr, **cptr1;
int mcnt, ccnt;
char **servers;
- int rc;
+ int rc, len;
if (ret == NULL || error == NULL) {
return (NS_LDAP_OP_FAILED);
@@ -157,18 +397,26 @@ __s_api_requestServer(const char *request, const char *server,
else
ireq = request;
- adata = (sizeof (ldap_call_t) + strlen(ireq) +1);
+ adata = (sizeof (ldap_call_t) + strlen(ireq) + strlen(addrType) + 1);
if (server != NULL) {
adata += strlen(DOORLINESEP) + 1;
adata += strlen(server) + 1;
}
ndata = sizeof (space);
+ len = sizeof (space) - sizeof (space.s_d.ldap_call.ldap_callnumber);
space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER;
- (void) strcpy(space.s_d.ldap_call.ldap_u.domainname, ireq);
+ if (strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len) >= len)
+ return (NS_LDAP_MEMORY);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname, addrType, len) >=
+ len)
+ return (NS_LDAP_MEMORY);
if (server != NULL) {
- (void) strcat(space.s_d.ldap_call.ldap_u.domainname,
- DOORLINESEP);
- (void) strcat(space.s_d.ldap_call.ldap_u.domainname, server);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname,
+ DOORLINESEP, len) >= len)
+ return (NS_LDAP_MEMORY);
+ if (strlcat(space.s_d.ldap_call.ldap_u.domainname, server,
+ len) >= len)
+ return (NS_LDAP_MEMORY);
}
sptr = &space.s_d;
@@ -327,86 +575,120 @@ __s_api_requestServer(const char *request, const char *server,
return (NS_LDAP_SUCCESS);
}
-#ifdef DEBUG
/*
* printCred(): prints the credential structure
*/
static void
-printCred(FILE *fp, const ns_cred_t *cred)
+printCred(int pri, const ns_cred_t *cred)
{
- if (fp == NULL) {
- (void) fprintf(fp, "printCred: fp is NULL\n");
- return;
- }
+ thread_t t = thr_self();
+
if (cred == NULL) {
- (void) fprintf(fp, "printCred: cred is NULL\n");
+ syslog(LOG_ERR, "tid= %d: printCred: cred is NULL\n", t);
return;
}
- (void) fprintf(fp, "AuthType=%d\n", cred->auth.type);
- (void) fprintf(fp, "TlsType=%d\n", cred->auth.tlstype);
- (void) fprintf(fp, "SaslMech=%d\n", cred->auth.saslmech);
- (void) fprintf(fp, "SaslOpt=%d\n", cred->auth.saslopt);
+ syslog(pri, "tid= %d: AuthType=%d", t, cred->auth.type);
+ syslog(pri, "tid= %d: TlsType=%d", t, cred->auth.tlstype);
+ syslog(pri, "tid= %d: SaslMech=%d", t, cred->auth.saslmech);
+ syslog(pri, "tid= %d: SaslOpt=%d", t, cred->auth.saslopt);
if (cred->hostcertpath)
- (void) fprintf(fp, "hostCertPath=%s\n", cred->hostcertpath);
+ syslog(pri, "tid= %d: hostCertPath=%s\n",
+ t, cred->hostcertpath);
if (cred->cred.unix_cred.userID)
- (void) fprintf(fp, "userID=%s\n", cred->cred.unix_cred.userID);
+ syslog(pri, "tid= %d: userID=%s\n",
+ t, cred->cred.unix_cred.userID);
if (cred->cred.unix_cred.passwd)
- (void) fprintf(fp, "passwd=%s\n", cred->cred.unix_cred.passwd);
+ syslog(pri, "tid= %d: passwd=%s\n",
+ t, cred->cred.unix_cred.passwd);
}
/*
* printConnection(): prints the connection structure
*/
static void
-printConnection(FILE *fp, Connection *con)
+printConnection(int pri, Connection *con)
{
- if (fp == NULL || con == NULL)
+ thread_t t = thr_self();
+
+ if (con == NULL)
return;
- (void) fprintf(fp, "connectionID=%d\n", con->connectionId);
- (void) fprintf(fp, "usedBit=%d\n", con->usedBit);
- (void) fprintf(fp, "threadID=%d\n", con->threadID);
+ syslog(pri, "tid= %d: connectionID=%d\n", t, con->connectionId);
+ syslog(pri, "tid= %d: shared=%d\n", t, con->shared);
+ syslog(pri, "tid= %d: usedBit=%d\n", t, con->usedBit);
+ syslog(pri, "tid= %d: threadID=%d\n", t, con->threadID);
if (con->serverAddr) {
- (void) fprintf(fp, "serverAddr=%s\n", con->serverAddr);
+ syslog(pri, "tid= %d: serverAddr=%s\n",
+ t, con->serverAddr);
}
- printCred(fp, con->auth);
- (void) fprintf(fp, "-----------------------------------------------\n");
- fflush(fp);
+ printCred(pri, con->auth);
}
-#endif /* DEBUG */
/*
- * addConnection(): inserts a connection in the connection list.
- * It will also sets use bit and the thread Id for the thread
- * using the connection for the first time.
+ * addConnection(): set up a connection so that it can be shared
+ * among multiple threads and then insert the connection in the
+ * connection list.
* Returns: -1 = failure, new Connection ID = success
+ *
+ * This function could exit with sessionLock locked. It will be
+ * be unlocked in __s_api_getConnection() when it exits without getting a
+ * connection.
*/
static int
addConnection(Connection *con)
{
- int i;
+ int i, noMTperC = 0;
+ thread_t t = thr_self();
+ struct ldap_thread_fns tfns;
+ void *tsd;
if (!con)
return (-1);
-#ifdef DEBUG
- (void) fprintf(stderr, "Adding connection thrid=%d\n", con->threadID);
-#endif /* DEBUG */
- (void) mutex_lock(&sessionPoolLock);
+
+ syslog(LOG_DEBUG, "tid= %d: Adding connection (serverAddr=%s)",
+ t, con->serverAddr);
+
+ if (MTperConn == 1) {
+ /*
+ * Make sure ld has proper thread functions and tsd
+ * is set up.
+ */
+ (void) memset(&tfns, 0, sizeof (struct ldap_thread_fns));
+ /*
+ * ldap_init sets ltf_get_lderrno and ltf_set_lderrno to NULLs.
+ * It's supposed to be overwritten by ns_setup_mt_conn_and_tsd.
+ */
+ if (ldap_get_option(con->ld, LDAP_OPT_THREAD_FN_PTRS,
+ (void *)&tfns) != 0 ||
+ tfns.ltf_get_lderrno != get_ld_error ||
+ tfns.ltf_set_lderrno != set_ld_error) {
+ MTperConn = 0;
+ noMTperC = 1;
+ } else {
+ if (thr_getspecific(ns_mtckey, &tsd) != 0 ||
+ tsd == NULL)
+ noMTperC = 1;
+ }
+
+ } else {
+ noMTperC = 1;
+ }
+
+ (void) rw_wrlock(&sessionPoolLock);
if (sessionPool == NULL) {
sessionPoolSize = SESSION_CACHE_INC;
sessionPool = calloc(sessionPoolSize,
sizeof (struct connection **));
if (!sessionPool) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
}
-#ifdef DEBUG
- (void) fprintf(stderr, "Initialized sessionPool\n");
-#endif /* DEBUG */
+
+ syslog(LOG_DEBUG, "tid= %d: Initialized sessionPool", t);
}
for (i = 0; (i < sessionPoolSize) && (sessionPool[i] != NULL); ++i)
;
@@ -417,26 +699,44 @@ addConnection(Connection *con)
(sessionPoolSize + SESSION_CACHE_INC) *
sizeof (Connection *));
if (!cl) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
}
(void) memset(cl + sessionPoolSize, 0,
SESSION_CACHE_INC * sizeof (struct connection *));
sessionPool = cl;
sessionPoolSize += SESSION_CACHE_INC;
-#ifdef DEBUG
- (void) fprintf(stderr, "Increased sessionPoolSize to: %d\n",
- sessionPoolSize);
-#endif /* DEBUG */
+ syslog(LOG_DEBUG, "tid: %d: Increased "
+ "sessionPoolSize to: %d\n",
+ t, sessionPoolSize);
}
sessionPool[i] = con;
- con->usedBit = B_TRUE;
- (void) mutex_unlock(&sessionPoolLock);
+ if (noMTperC == 0)
+ con->shared++;
+ else
+ con->usedBit = B_TRUE;
+
+ (void) rw_unlock(&sessionPoolLock);
+
con->connectionId = i + CONID_OFFSET;
-#ifdef DEBUG
- (void) fprintf(stderr, "Connection added [%d]\n", i);
- printConnection(stderr, con);
-#endif /* DEBUG */
+
+ syslog(LOG_DEBUG, "tid= %d: Connection added [%d]\n",
+ t, i);
+ printConnection(LOG_DEBUG, con);
+
+ /*
+ * A connection can be shared now, unlock
+ * the session mutex and let other
+ * threads try to use this connection or
+ * get their own.
+ */
+ if (wait4session != 0 && sessionTid == thr_self()) {
+ wait4session = 0;
+ sessionTid = 0;
+ syslog(LOG_DEBUG, "tid= %d: unlocking sessionLock\n", t);
+ (void) mutex_unlock(&sessionLock);
+ }
+
return (i + CONID_OFFSET);
}
@@ -453,6 +753,11 @@ findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID,
if ((conp == NULL) || (auth == NULL) || cID < CONID_OFFSET)
return (-1);
+
+ /* if a new connection is requested, no need to continue */
+ if (flags & NS_LDAP_NEW_CONN)
+ return (-1);
+
*conp = NULL;
if (sessionPool == NULL)
return (-1);
@@ -460,9 +765,9 @@ findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID,
if (id < 0 || id >= sessionPoolSize)
return (-1);
- (void) mutex_lock(&sessionPoolLock);
+ (void) rw_rdlock(&sessionPoolLock);
if (sessionPool[id] == NULL) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
}
cp = sessionPool[id];
@@ -471,11 +776,12 @@ findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID,
* Make sure the connection has the same type of authentication method
*/
if ((cp->usedBit) ||
+ (cp->notAvail) ||
(cp->auth->auth.type != auth->auth.type) ||
(cp->auth->auth.tlstype != auth->auth.tlstype) ||
(cp->auth->auth.saslmech != auth->auth.saslmech) ||
(cp->auth->auth.saslopt != auth->auth.saslopt)) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
}
if ((((cp->auth->auth.type == NS_LDAP_AUTH_SASL) &&
@@ -485,18 +791,19 @@ findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID,
((cp->auth->cred.unix_cred.userID == NULL) ||
(strcasecmp(cp->auth->cred.unix_cred.userID,
auth->cred.unix_cred.userID) != 0))) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
}
+
/* An existing connection is found but it needs to be reset */
if (flags & NS_LDAP_NEW_CONN) {
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
DropConnection(cID, 0);
return (-1);
}
/* found an available connection */
cp->usedBit = B_TRUE;
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
cp->threadID = thr_self();
*conp = cp;
return (cID);
@@ -508,39 +815,111 @@ findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID,
* If serverAddr is NULL, then find a connection to any server
* as long as it matches the rest of the parameters.
* Returns: -1 = failure, the Connection ID found = success.
+ *
+ * This function could exit with sessionLock locked. It will be
+ * be unlocked in addConnection() when this thread adds the connection
+ * to the pool or in __s_api_getConnection() when it exits without getting a
+ * connection.
*/
+#define TRY_TIMES 10
static int
-findConnection(const char *serverAddr, const ns_cred_t *auth, Connection **conp)
+findConnection(int flags, const char *serverAddr,
+ const ns_cred_t *auth, Connection **conp)
{
Connection *cp;
int i;
+ int rc;
+ int try;
+#ifdef DEBUG
+ thread_t t = thr_self();
+#endif /* DEBUG */
if (auth == NULL || conp == NULL)
return (-1);
*conp = NULL;
+ /* no need to find connection if anonymous */
+ if (auth->auth.type == NS_LDAP_AUTH_NONE)
+ return (-1);
+
+ /* if a new connection is requested, no need to continue */
+ if (flags & NS_LDAP_NEW_CONN)
+ return (-1);
+
#ifdef DEBUG
- (void) fprintf(stderr, "Find connection\n");
- (void) fprintf(stderr, "Looking for ....\n");
+ (void) fprintf(stderr, "tid= %d: Find connection\n", t);
+ (void) fprintf(stderr, "tid= %d: Looking for ....\n", t);
if (serverAddr && *serverAddr)
- (void) fprintf(stderr, "serverAddr=%s\n", serverAddr);
+ (void) fprintf(stderr, "tid= %d: serverAddr=%s\n",
+ t, serverAddr);
else
- (void) fprintf(stderr, "serverAddr=NULL\n");
+ (void) fprintf(stderr, "tid= %d: serverAddr=NULL\n", t);
printCred(stderr, auth);
fflush(stderr);
#endif /* DEBUG */
- if (sessionPool == NULL)
+
+ /*
+ * If multiple threads per connection not supported,
+ * no sessionPool means no connection
+ */
+ (void) rw_rdlock(&sessionPoolLock);
+ if (MTperConn == 0 && sessionPool == NULL) {
+ (void) rw_unlock(&sessionPoolLock);
return (-1);
- (void) mutex_lock(&sessionPoolLock);
+ }
+
+ /*
+ * If no connection in cache, then serialize the opening
+ * of connections. Make sure only one is being opened
+ * at a time. Otherwise, we may end up with more
+ * connections than we want (if multiple threads get
+ * here at the same time)
+ */
+ if (sessionPool == NULL) {
+ (void) rw_unlock(&sessionPoolLock);
+ (void) mutex_lock(&sessionLock);
+ if (sessionPool == NULL) {
+ wait4session = 1;
+ sessionTid = thr_self();
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: get "
+ "connection ... \n", t);
+ fflush(stderr);
+#endif /* DEBUG */
+ /*
+ * Exit with sessionLock locked. It will be
+ * be unlocked in addConnection() when this
+ * thread adds the connection to the pool or
+ * in __s_api_getConnection() when it exits
+ * without getting a connection.
+ */
+ return (-1);
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: session pool not empty\n", t);
+ fflush(stderr);
+#endif /* DEBUG */
+ /*
+ * connection pool is not empty, check to see if
+ * one can be shared.
+ */
+ (void) mutex_unlock(&sessionLock);
+ (void) rw_rdlock(&sessionPoolLock);
+ }
+ try = 0;
+ check_again:
+
for (i = 0; i < sessionPoolSize; ++i) {
if (sessionPool[i] == NULL)
continue;
cp = sessionPool[i];
#ifdef DEBUG
- (void) fprintf(stderr, "checking connection [%d] ....\n", i);
+ (void) fprintf(stderr, "tid= %d: checking connection "
+ "[%d] ....\n", t, i);
printConnection(stderr, cp);
#endif /* DEBUG */
- if ((cp->usedBit) ||
+ if ((cp->usedBit) || (cp->notAvail) ||
(cp->auth->auth.type != auth->auth.type) ||
(cp->auth->auth.tlstype != auth->auth.tlstype) ||
(cp->auth->auth.saslmech != auth->auth.saslmech) ||
@@ -560,18 +939,89 @@ findConnection(const char *serverAddr, const ns_cred_t *auth, Connection **conp)
auth->cred.unix_cred.passwd) != 0))))
continue;
/* found an available connection */
- cp->usedBit = B_TRUE;
- (void) mutex_unlock(&sessionPoolLock);
- cp->threadID = thr_self();
+ if (MTperConn == 0)
+ cp->usedBit = B_TRUE;
+ else {
+ /* allocate TSD for per thread ldap error */
+ rc = tsd_setup();
+
+ /* if we got TSD, this connection is shared */
+ if (rc != -1)
+ cp->shared++;
+ else if (cp->shared == 0) {
+ cp->usedBit = B_TRUE;
+ cp->threadID = thr_self();
+ (void) rw_unlock(&sessionPoolLock);
+ return (-1);
+ }
+ }
+ (void) rw_unlock(&sessionPoolLock);
+
*conp = cp;
#ifdef DEBUG
- (void) fprintf(stderr, "Connection found cID=%d\n", i);
+ (void) fprintf(stderr, "tid= %d: Connection found "
+ "cID=%d, shared =%d\n", t, i, cp->shared);
fflush(stderr);
#endif /* DEBUG */
return (i + CONID_OFFSET);
}
- (void) mutex_unlock(&sessionPoolLock);
- return (-1);
+ (void) rw_unlock(&sessionPoolLock);
+
+ /*
+ * If multiple threads per connection not supported,
+ * we are done, just return -1 to tell the caller to
+ * proceed with opening a connection
+ */
+ if (MTperConn == 0)
+ return (-1);
+
+ /*
+ * No connection can be shared, test to see if
+ * one is being opened. If trylock returns
+ * EBUSY then it is, so wait until the opening
+ * is done and try to see if the new connection
+ * can be shared.
+ */
+ rc = mutex_trylock(&sessionLock);
+ if (rc == EBUSY) {
+ (void) mutex_lock(&sessionLock);
+ (void) mutex_unlock(&sessionLock);
+ (void) rw_rdlock(&sessionPoolLock);
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: check session "
+ "pool again\n", t);
+ fflush(stderr);
+#endif /* DEBUG */
+ if (try < TRY_TIMES) {
+ try++;
+ goto check_again;
+ } else {
+ syslog(LOG_WARNING, "libsldap: mutex_trylock "
+ "%d times. Stop.", TRY_TIMES);
+ return (-1);
+ }
+ } else if (rc == 0) {
+ /*
+ * No connection can be shared, none being opened,
+ * exit with sessionLock locked to open one. The
+ * mutex will be unlocked in addConnection() when
+ * this thread adds the new connection to the pool
+ * or in __s_api_getConnection() when it exits
+ * without getting a connection.
+ */
+ wait4session = 1;
+ sessionTid = thr_self();
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: no connection found, "
+ "none being opened, get connection ...\n", t);
+ fflush(stderr);
+#endif /* DEBUG */
+ return (-1);
+ } else {
+ syslog(LOG_WARNING, "libsldap: mutex_trylock unexpected "
+ "error", rc);
+ return (-1);
+ }
}
/*
@@ -607,7 +1057,7 @@ static int
makeConnection(Connection **conp, const char *serverAddr,
const ns_cred_t *auth, ConnectionID *cID, int timeoutSec,
ns_ldap_error_t **errorp, int fail_if_new_pwd_reqd,
- int nopasswd_acct_mgmt, char ***badsrvrs)
+ int nopasswd_acct_mgmt, int flags, char ***badsrvrs)
{
Connection *con = NULL;
ConnectionID id;
@@ -618,7 +1068,9 @@ makeConnection(Connection **conp, const char *serverAddr,
LDAP *ld = NULL;
int passwd_mgmt = 0;
int totalbad = 0; /* Number of servers contacted unsuccessfully */
- short memerr = 0; /* Variable for tracking memory allocation errors */
+ short memerr = 0; /* Variable for tracking memory allocation */
+ char *serverAddrType = NULL;
+
if (conp == NULL || errorp == NULL || auth == NULL)
return (NS_LDAP_INVALID_PARAM);
@@ -628,10 +1080,11 @@ makeConnection(Connection **conp, const char *serverAddr,
sinfo.controls = NULL;
sinfo.saslMechanisms = NULL;
- if ((id = findConnection(serverAddr, auth, &con)) != -1) {
+ if ((id = findConnection(flags, serverAddr, auth, &con)) != -1) {
/* connection found in cache */
#ifdef DEBUG
- (void) fprintf(stderr, "connection found in cache %d\n", id);
+ (void) fprintf(stderr, "tid= %d: connection found in "
+ "cache %d\n", thr_self(), id);
fflush(stderr);
#endif /* DEBUG */
*cID = id;
@@ -639,21 +1092,26 @@ makeConnection(Connection **conp, const char *serverAddr,
return (NS_LDAP_SUCCESS);
}
+ if (auth->auth.saslmech == NS_LDAP_SASL_GSSAPI)
+ serverAddrType = NS_CACHE_ADDR_HOSTNAME;
+ else
+ serverAddrType = NS_CACHE_ADDR_IP;
+
if (serverAddr) {
- rc = openConnection(&ld, serverAddr, auth, timeoutSec, errorp,
+ rc = __s_api_requestServer(NS_CACHE_NEW, serverAddr,
+ &sinfo, errorp, serverAddrType);
+ if (rc != NS_LDAP_SUCCESS || sinfo.server == NULL) {
+ (void) snprintf(errmsg, sizeof (errmsg),
+ gettext("makeConnection: unable to get "
+ "server information for %s"), serverAddr);
+ syslog(LOG_ERR, "libsldap: %s", errmsg);
+ return (NS_LDAP_OP_FAILED);
+ }
+ rc = openConnection(&ld, sinfo.server, auth, timeoutSec, errorp,
fail_if_new_pwd_reqd, passwd_mgmt);
if (rc == NS_LDAP_SUCCESS || rc ==
NS_LDAP_SUCCESS_WITH_INFO) {
exit_rc = rc;
- rc = __s_api_requestServer(NS_CACHE_NEW, serverAddr,
- &sinfo, errorp);
- if (rc != NS_LDAP_SUCCESS || sinfo.server == NULL) {
- (void) snprintf(errmsg, sizeof (errmsg),
- gettext("makeConnection: unable to get "
- "server information for %s"), serverAddr);
- syslog(LOG_ERR, "libsldap: %s", errmsg);
- return (NS_LDAP_OP_FAILED);
- }
goto create_con;
} else {
return (rc);
@@ -666,7 +1124,8 @@ makeConnection(Connection **conp, const char *serverAddr,
hReq = NS_CACHE_NEW;
else
hReq = NS_CACHE_NEXT;
- rc = __s_api_requestServer(hReq, host, &sinfo, errorp);
+ rc = __s_api_requestServer(hReq, host, &sinfo, errorp,
+ serverAddrType);
if ((rc != NS_LDAP_SUCCESS) || (sinfo.server == NULL) ||
(host && (strcasecmp(host, sinfo.server) == 0))) {
/* Log the error */
@@ -851,6 +1310,7 @@ create_con:
}
con->threadID = thr_self();
+
con->ld = ld;
if ((id = addConnection(con)) == -1) {
freeConnection(con);
@@ -866,7 +1326,8 @@ create_con:
return (NS_LDAP_MEMORY);
}
#ifdef DEBUG
- (void) fprintf(stderr, "connection added into cache %d\n", id);
+ (void) fprintf(stderr, "tid= %d: connection added into "
+ "cache %d\n", thr_self(), id);
fflush(stderr);
#endif /* DEBUG */
*cID = id;
@@ -884,42 +1345,86 @@ _DropConnection(ConnectionID cID, int flag, int fini)
{
Connection *cp;
int id;
- int use_mutex = !fini;
+ int use_lock = !fini;
+#ifdef DEBUG
+ thread_t t = thr_self();
+#endif /* DEBUG */
id = cID - CONID_OFFSET;
if (id < 0 || id >= sessionPoolSize)
return;
#ifdef DEBUG
- (void) fprintf(stderr,
- "Dropping connection cID=%d flag=0x%x\n", cID, flag);
+ (void) fprintf(stderr, "tid= %d: "
+ "Dropping connection cID=%d flag=0x%x, fini = %d\n",
+ t, cID, flag, fini);
fflush(stderr);
#endif /* DEBUG */
- if (use_mutex)
- (void) mutex_lock(&sessionPoolLock);
+ if (use_lock)
+ (void) rw_wrlock(&sessionPoolLock);
cp = sessionPool[id];
/* sanity check before removing */
- if (!cp || (!fini && (!cp->usedBit || cp->threadID != thr_self()))) {
- if (use_mutex)
- (void) mutex_unlock(&sessionPoolLock);
+ if (!cp || (!fini && !cp->shared && (!cp->usedBit ||
+ cp->threadID != thr_self()))) {
+#ifdef DEBUG
+ if (cp == NULL)
+ (void) fprintf(stderr, "tid= %d: no "
+ "need to remove (fini = %d, cp = %p)\n", t,
+ fini, cp);
+ else
+ (void) fprintf(stderr, "tid= %d: no "
+ "need to remove (fini = %d, cp = %p, shared = %d)\n",
+ t, fini, cp, cp->shared);
+ fflush(stderr);
+#endif /* DEBUG */
+ if (use_lock)
+ (void) rw_unlock(&sessionPoolLock);
return;
}
if (!fini &&
- ((flag & NS_LDAP_NEW_CONN) == 0) &&
- ((flag & NS_LDAP_KEEP_CONN) || nscd_proc())) {
+ ((flag & NS_LDAP_NEW_CONN) == 0) && !cp->notAvail &&
+ ((flag & NS_LDAP_KEEP_CONN) ||
+ (MTperConn == 0 && nscd_proc()) ||
+ MTperConn)) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: keep alive (fini = %d "
+ "shared = %d)\n", t, fini, cp->shared);
+#endif /* DEBUG */
/* release Connection (keep alive) */
+ if (cp->shared)
+ cp->shared--;
cp->usedBit = B_FALSE;
cp->threadID = 0; /* unmark the threadID */
- if (use_mutex)
- (void) mutex_unlock(&sessionPoolLock);
+ if (use_lock)
+ (void) rw_unlock(&sessionPoolLock);
} else {
/* delete Connection (disconnect) */
- sessionPool[id] = NULL;
- if (use_mutex)
- (void) mutex_unlock(&sessionPoolLock);
- (void) ldap_unbind(cp->ld);
- freeConnection(cp);
+ if (cp->shared > 0) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: Connection no "
+ "longer available (fini = %d, shared = %d)\n",
+ t, fini, cp->shared);
+ fflush(stderr);
+#endif /* DEBUG */
+ cp->shared--;
+ cp->notAvail = 1;
+ }
+
+ if (cp->shared <= 0) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: unbind "
+ "(fini = %d, shared = %d)\n",
+ t, fini, cp->shared);
+ fflush(stderr);
+#endif /* DEBUG */
+ sessionPool[id] = NULL;
+ (void) ldap_unbind(cp->ld);
+ freeConnection(cp);
+ }
+
+ if (use_lock)
+ (void) rw_unlock(&sessionPoolLock);
}
}
@@ -1189,16 +1694,17 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
int errnum = 0;
LDAPMessage *resultMsg;
int msgId;
- int useSSL = 0;
+ int useSSL = 0, port = 0;
struct timeval tv;
AuthType_t bindType;
int timeoutMilliSec = timeoutSec * 1000;
struct berval cred;
char *sslServerAddr;
char *s1;
- char *errmsg;
+ char *errmsg, *end = NULL;
LDAPControl **controls;
- int pwd_rc;
+ int pwd_rc, min_ssf = MIN_SASL_SSF, max_ssf = MAX_SASL_SSF;
+ ns_sasl_cb_param_t sasl_param;
*errorp = NULL;
*ldp = NULL;
@@ -1246,7 +1752,8 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
const char *hostcertpath;
char *alloc_hcp = NULL;
#ifdef DEBUG
- (void) fprintf(stderr, "+++TLS transport\n");
+ (void) fprintf(stderr, "tid= %d: +++TLS transport\n",
+ thr_self());
#endif /* DEBUG */
if (prldap_set_session_option(NULL, NULL,
@@ -1324,15 +1831,40 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
}
} else {
#ifdef DEBUG
- (void) fprintf(stderr, "+++Unsecure transport\n");
+ (void) fprintf(stderr, "tid= %d: +++Unsecure transport\n",
+ thr_self());
#endif /* DEBUG */
- /* Warning message IF cannot connect to host(s) */
- if ((ld = ldap_init((char *)serverAddr, LDAP_PORT)) == NULL) {
+ port = LDAP_PORT;
+ if (auth->auth.saslmech == NS_LDAP_SASL_GSSAPI &&
+ (end = strchr(serverAddr, ':')) != NULL) {
+ /*
+ * The IP is converted to hostname so it's a
+ * hostname:port up to this point.
+ *
+ * libldap passes hostname:port to the sasl layer.
+ * The ldap service principal is constructed as
+ * ldap/hostname:port@REALM. Kerberos authentication
+ * will fail. So it needs to be parsed to construct
+ * a valid principal ldap/hostname@REALM.
+ *
+ * For useSSL case above, it already parses port so
+ * no need to parse serverAddr
+ */
+ *end = '\0';
+ port = atoi(end + 1);
+ }
+
+ /* Warning message IF cannot connect to host(s) */
+ if ((ld = ldap_init((char *)serverAddr, port)) == NULL) {
char *p = strerror(errno);
MKERROR(LOG_WARNING, *errorp, LDAP_CONNECT_ERROR,
strdup(p), NULL);
+ if (end)
+ *end = ':';
return (NS_LDAP_INTERNAL);
} else {
+ if (end)
+ *end = ':';
/* check and avoid gethostname recursion */
if (ldap_in_hosts_switch() > 0 &&
! __s_api_isipv4((char *)serverAddr) &&
@@ -1340,21 +1872,22 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
/* host: ldap - found, attempt to recover */
if (ldap_set_option(ld, LDAP_X_OPT_DNS_SKIPDB,
"ldap") != 0) {
- (void) snprintf(errstr, sizeof (errstr),
- gettext("openConnection: "
- "unrecoverable gethostname "
- "recursion detected "
- "in /etc/nsswitch.conf"));
- MKERROR(LOG_WARNING, *errorp,
- LDAP_CONNECT_ERROR,
- strdup(errstr), NULL);
- (void) ldap_unbind(ld);
- return (NS_LDAP_INTERNAL);
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("openConnection: "
+ "unrecoverable gethostname "
+ "recursion detected "
+ "in /etc/nsswitch.conf"));
+ MKERROR(LOG_WARNING, *errorp,
+ LDAP_CONNECT_ERROR,
+ strdup(errstr), NULL);
+ (void) ldap_unbind(ld);
+ return (NS_LDAP_INTERNAL);
}
}
}
}
+ ns_setup_mt_conn_and_tsd(ld);
(void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion);
(void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption);
/*
@@ -1377,7 +1910,8 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
switch (bindType) {
case NS_LDAP_AUTH_NONE:
#ifdef DEBUG
- (void) fprintf(stderr, "+++Anonymous bind\n");
+ (void) fprintf(stderr, "tid= %d: +++Anonymous bind\n",
+ thr_self());
#endif /* DEBUG */
break;
case NS_LDAP_AUTH_SIMPLE:
@@ -1394,7 +1928,8 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
}
#ifdef DEBUG
- (void) fprintf(stderr, "+++Simple bind\n");
+ (void) fprintf(stderr, "tid= %d: +++Simple bind\n",
+ thr_self());
#endif /* DEBUG */
msgId = ldap_simple_bind(ld, binddn, passwd);
@@ -1462,31 +1997,35 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
break;
case NS_LDAP_AUTH_SASL:
- /* We don't support any sasl options yet */
- if (auth->auth.saslopt != NS_LDAP_SASLOPT_NONE) {
+ if (auth->auth.saslopt != NS_LDAP_SASLOPT_NONE &&
+ auth->auth.saslmech != NS_LDAP_SASL_GSSAPI) {
(void) sprintf(errstr,
gettext("openConnection: SASL options are "
- "not supported (%d)"), auth->auth.saslopt);
+ "not supported (%d) for non-GSSAPI sasl bind"),
+ auth->auth.saslopt);
MKERROR(LOG_WARNING, *errorp,
LDAP_AUTH_METHOD_NOT_SUPPORTED,
strdup(errstr), NULL);
(void) ldap_unbind(ld);
return (NS_LDAP_INTERNAL);
}
- binddn = auth->cred.unix_cred.userID;
- passwd = auth->cred.unix_cred.passwd;
- if (passwd == NULL || *passwd == '\0' ||
- binddn == NULL || *binddn == '\0') {
- (void) sprintf(errstr,
+ if (auth->auth.saslmech != NS_LDAP_SASL_GSSAPI) {
+ binddn = auth->cred.unix_cred.userID;
+ passwd = auth->cred.unix_cred.passwd;
+ if (passwd == NULL || *passwd == '\0' ||
+ binddn == NULL || *binddn == '\0') {
+ (void) sprintf(errstr,
gettext("openConnection: missing credentials "
"for SASL bind"));
- MKERROR(LOG_WARNING, *errorp, LDAP_INVALID_CREDENTIALS,
- strdup(errstr), NULL);
- (void) ldap_unbind(ld);
- return (NS_LDAP_INTERNAL);
+ MKERROR(LOG_WARNING, *errorp,
+ LDAP_INVALID_CREDENTIALS,
+ strdup(errstr), NULL);
+ (void) ldap_unbind(ld);
+ return (NS_LDAP_INTERNAL);
+ }
+ cred.bv_val = passwd;
+ cred.bv_len = strlen(passwd);
}
- cred.bv_val = passwd;
- cred.bv_len = strlen(passwd);
switch (auth->auth.saslmech) {
case NS_LDAP_SASL_CRAM_MD5:
@@ -1584,6 +2123,47 @@ openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
free(digest_md5_name);
break;
+ case NS_LDAP_SASL_GSSAPI:
+ if (sasl_gssapi_inited == 0) {
+ rc = __s_api_sasl_gssapi_init();
+ if (rc != NS_LDAP_SUCCESS) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("openConnection: "
+ "GSSAPI initialization "
+ "failed"));
+ (void) ldap_unbind(ld);
+ MKERROR(LOG_WARNING, *errorp, rc,
+ strdup(errstr), NULL);
+ return (rc);
+ }
+ }
+ (void) memset(&sasl_param, 0,
+ sizeof (ns_sasl_cb_param_t));
+ sasl_param.authid = NULL;
+ sasl_param.authzid = "";
+ (void) ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MIN,
+ (void *)&min_ssf);
+ (void) ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX,
+ (void *)&max_ssf);
+
+ rc = ldap_sasl_interactive_bind_s(
+ ld, NULL, "GSSAPI",
+ NULL, NULL, LDAP_SASL_INTERACTIVE,
+ __s_api_sasl_bind_callback,
+ &sasl_param);
+
+ if (rc != LDAP_SUCCESS) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("openConnection: "
+ "GSSAPI bind failed "
+ "- %d %s"), rc, ldap_err2string(rc));
+ (void) ldap_unbind(ld);
+ MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL,
+ strdup(errstr), NULL);
+ return (NS_LDAP_INTERNAL);
+ }
+
+ break;
default:
(void) ldap_unbind(ld);
(void) sprintf(errstr,
@@ -1648,12 +2228,11 @@ __s_api_getDefaultAuth(
return (NS_LDAP_INVALID_PARAM);
}
-
/*
- * Do not differentiate between (proxy/self) at this time, but
- * reject self credential levels at this time
+ * credential level "self" can work with auth method sasl/GSSAPI only
*/
- if (cLevel && *cLevel == NS_LDAP_CRED_SELF)
+ if (cLevel && *cLevel == NS_LDAP_CRED_SELF &&
+ aMethod->saslmech != NS_LDAP_SASL_GSSAPI)
return (NS_LDAP_INVALID_PARAM);
*authp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t));
@@ -1674,7 +2253,7 @@ __s_api_getDefaultAuth(
(aMethod->saslmech == NS_LDAP_SASL_CRAM_MD5)) {
getUid++;
getPasswd++;
- } else {
+ } else if (aMethod->saslmech != NS_LDAP_SASL_GSSAPI) {
(void) __ns_ldap_freeCred(authp);
*authp = NULL;
return (NS_LDAP_INVALID_PARAM);
@@ -1845,7 +2424,7 @@ __s_api_getConnection(
int sec = 1;
ns_cred_t *authp = NULL;
ns_cred_t anon;
- int version = NS_LDAP_V2;
+ int version = NS_LDAP_V2, self_gssapi_only = 0;
void **paramVal = NULL;
char **badSrvrs = NULL; /* List of problem hostnames */
@@ -1941,16 +2520,20 @@ __s_api_getConnection(
/* using specified auth method */
rc = makeConnection(&con, server, cred,
sessionId, timeoutSec, errorp,
- fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
- &badSrvrs);
+ fail_if_new_pwd_reqd,
+ nopasswd_acct_mgmt, flags, &badSrvrs);
if (rc == NS_LDAP_SUCCESS ||
rc == NS_LDAP_SUCCESS_WITH_INFO) {
*session = con;
break;
}
} else {
+ self_gssapi_only = __s_api_self_gssapi_only_get();
/* for every cred level */
for (cNext = cLevel; *cNext != NULL; cNext++) {
+ if (self_gssapi_only &&
+ **cNext != NS_LDAP_CRED_SELF)
+ continue;
if (**cNext == NS_LDAP_CRED_ANON) {
/*
* make connection anonymously
@@ -1964,7 +2547,8 @@ __s_api_getConnection(
rc = makeConnection(&con, server, &anon,
sessionId, timeoutSec, errorp,
fail_if_new_pwd_reqd,
- nopasswd_acct_mgmt, &badSrvrs);
+ nopasswd_acct_mgmt, flags,
+ &badSrvrs);
if (rc == NS_LDAP_SUCCESS ||
rc ==
NS_LDAP_SUCCESS_WITH_INFO) {
@@ -1975,6 +2559,22 @@ __s_api_getConnection(
}
/* for each cred level */
for (aNext = aMethod; *aNext != NULL; aNext++) {
+ if (self_gssapi_only &&
+ (*aNext)->saslmech !=
+ NS_LDAP_SASL_GSSAPI)
+ continue;
+ /*
+ * self coexists with sasl/GSSAPI only
+ * and non-self coexists with non-gssapi
+ * only
+ */
+ if ((**cNext == NS_LDAP_CRED_SELF &&
+ (*aNext)->saslmech !=
+ NS_LDAP_SASL_GSSAPI) ||
+ (**cNext != NS_LDAP_CRED_SELF &&
+ (*aNext)->saslmech ==
+ NS_LDAP_SASL_GSSAPI))
+ continue;
/* make connection and authenticate */
/* with default credentials */
authp = NULL;
@@ -1994,7 +2594,8 @@ __s_api_getConnection(
rc = makeConnection(&con, server, authp,
sessionId, timeoutSec, errorp,
fail_if_new_pwd_reqd,
- nopasswd_acct_mgmt, &badSrvrs);
+ nopasswd_acct_mgmt, flags,
+ &badSrvrs);
(void) __ns_ldap_freeCred(&authp);
if (rc == NS_LDAP_SUCCESS ||
rc ==
@@ -2015,6 +2616,30 @@ __s_api_getConnection(
}
done:
+ /*
+ * If unable to get a connection, and this is
+ * the thread opening the shared connection,
+ * unlock the session mutex and let other
+ * threads try to get their own connection.
+ */
+ if (wait4session != 0 && sessionTid == thr_self()) {
+ wait4session = 0;
+ sessionTid = 0;
+#ifdef DEBUG
+ (void) fprintf(stderr, "tid= %d: __s_api_getConnection: "
+ "unlocking sessionLock \n", thr_self());
+ fflush(stderr);
+#endif /* DEBUG */
+ (void) mutex_unlock(&sessionLock);
+ }
+ if (self_gssapi_only && rc == NS_LDAP_SUCCESS && *session == NULL) {
+ /*
+ * self_gssapi_only is true but no self/sasl/gssapi is
+ * configured
+ */
+ rc = NS_LDAP_CONFIG;
+ }
+
(void) __ns_ldap_freeParam((void ***)&aMethod);
(void) __ns_ldap_freeParam((void ***)&cLevel);
@@ -2038,7 +2663,7 @@ _free_sessionPool()
{
int id;
- (void) mutex_lock(&sessionPoolLock);
+ (void) rw_wrlock(&sessionPoolLock);
if (sessionPool != NULL) {
for (id = 0; id < sessionPoolSize; id++)
_DropConnection(id + CONID_OFFSET, 0, 1);
@@ -2046,5 +2671,5 @@ _free_sessionPool()
sessionPool = NULL;
sessionPoolSize = 0;
}
- (void) mutex_unlock(&sessionPoolLock);
+ (void) rw_unlock(&sessionPoolLock);
}
diff --git a/usr/src/lib/libsldap/common/ns_init.c b/usr/src/lib/libsldap/common/ns_init.c
index e95a99375f..e9b6842210 100644
--- a/usr/src/lib/libsldap/common/ns_init.c
+++ b/usr/src/lib/libsldap/common/ns_init.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,11 +27,25 @@
#include "ns_sldap.h"
#include "ns_internal.h"
+#include <syslog.h>
#pragma init(ns_ldap_init)
+thread_key_t ns_mtckey;
+
static void
ns_ldap_init()
{
get_environment(); /* load environment debugging options */
+
+ /*
+ * ns_mtckey is needed to allow the sharing of an
+ * ldap connection among multiple threads. Used
+ * mainly in ns_connect.c.
+ */
+ if (thr_keycreate(&ns_mtckey, ns_tsd_cleanup) != 0) {
+ syslog(LOG_ERR, "libsldap: unable to create the thread "
+ "key needed for sharing ldap connections");
+ MTperConn = 0;
+ }
}
diff --git a/usr/src/lib/libsldap/common/ns_internal.h b/usr/src/lib/libsldap/common/ns_internal.h
index 07fc60149e..699cb1dfa0 100644
--- a/usr/src/lib/libsldap/common/ns_internal.h
+++ b/usr/src/lib/libsldap/common/ns_internal.h
@@ -474,7 +474,7 @@ typedef enum EnumAuthType {
NS_LDAP_EA_SASL_DIGEST_MD5_INT = 5,
NS_LDAP_EA_SASL_DIGEST_MD5_CONF = 6,
NS_LDAP_EA_SASL_EXTERNAL = 7,
- NS_LDAP_EA_SASL_GSSAPI = 8, /* unsupported */
+ NS_LDAP_EA_SASL_GSSAPI = 8,
NS_LDAP_EA_SASL_SPNEGO = 9, /* unsupported */
NS_LDAP_EA_TLS_NONE = 10,
NS_LDAP_EA_TLS_SIMPLE = 11,
@@ -549,9 +549,15 @@ typedef int ConnectionID;
*/
typedef struct connection {
ConnectionID connectionId;
- boolean_t usedBit;
+ boolean_t usedBit; /* true if only used by */
+ /* one thread and not shared */
+ /* by other threads */
+ boolean_t notAvail; /* not sharable, delete */
+ /* when shared == 0 */
+ int shared; /* number of threads */
+ /* using this connection */
char *serverAddr;
- ns_cred_t *auth;
+ ns_cred_t *auth;
LDAP *ld;
thread_t threadID; /* thread ID using it */
struct ns_ldap_cookie *cookieInfo;
@@ -664,6 +670,23 @@ typedef struct ns_server_info {
} ns_server_info_t;
/*
+ * sasl callback function parameters
+ */
+typedef struct ns_sasl_cb_param {
+ char *mech;
+ char *authid;
+ char *authzid;
+ char *passwd;
+ char *realm;
+} ns_sasl_cb_param_t;
+
+/* self/sasl/gssapi variable */
+extern int sasl_gssapi_inited;
+
+/* Multiple threads per connection variable */
+extern int MTperConn;
+
+/*
* INTERNAL GLOBAL DEFINITIONS AND FUNCTION DECLARATIONS
*/
@@ -748,6 +771,29 @@ ns_ldap_error_t *__ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname);
ns_ldap_error_t *__ns_ldap_DumpConfiguration(char *filename);
ns_ldap_error_t *__ns_ldap_DumpLdif(char *filename);
int __ns_ldap_cache_ping();
+ns_ldap_error_t *__ns_ldap_print_config(int);
+void __ns_ldap_default_config();
+int __ns_ldap_download(const char *, char *, char *,
+ ns_ldap_error_t **);
+int
+__ns_ldap_check_dns_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ const char *fname,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
+int
+__ns_ldap_check_gssapi_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
+int
+__ns_ldap_check_all_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp);
/* internal un-exposed APIs */
ns_cred_t *__ns_ldap_dupAuth(const ns_cred_t *authp);
@@ -804,6 +850,19 @@ int __s_api_contain_account_usable_control_oid(char **oids);
char *__s_api_get_canonical_name(ns_ldap_entry_t *entry,
ns_ldap_attr_t *attrptr, int case_ignore);
+/* self/sasl/gssapi functions */
+int __s_api_sasl_bind_callback(
+ LDAP *ld,
+ unsigned flags,
+ void *defaults,
+ void *in);
+
+int __s_api_self_gssapi_only_get(void);
+int __s_api_sasl_gssapi_init(void);
+
+/* Multiple threads per connection functions */
+void ns_tsd_cleanup(void *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libsldap/common/ns_reads.c b/usr/src/lib/libsldap/common/ns_reads.c
index 8db18695c4..3239ab9a55 100644
--- a/usr/src/lib/libsldap/common/ns_reads.c
+++ b/usr/src/lib/libsldap/common/ns_reads.c
@@ -2220,10 +2220,18 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle)
LDAP_ERROR;
}
if (cookie->connectionId > -1) {
- DropConnection(
+ /*
+ * NS_LDAP_NEW_CONN
+ * indicates that the
+ * connection should
+ * be deleted, not
+ * kept alive
+ */
+ DropConnection(
cookie->connectionId,
NS_LDAP_NEW_CONN);
- cookie->connectionId = -1;
+ cookie->connectionId =
+ -1;
}
}
break;
@@ -3022,7 +3030,7 @@ __ns_ldap_auth(const ns_cred_t *auth,
if (!auth)
return (NS_LDAP_INVALID_PARAM);
- rc = __s_api_getConnection(NULL, flags,
+ rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN,
auth, &connectionId, &conp, errorp,
do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt);
if (rc == NS_LDAP_OP_FAILED && *errorp)
@@ -3047,6 +3055,20 @@ __ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname)
return (NULL);
}
+ns_ldap_attr_t *
+__ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname)
+{
+ int i;
+
+ if (entry == NULL)
+ return (NULL);
+ for (i = 0; i < entry->attr_count; i++) {
+ if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL)
+ return (entry->attr_pair[i]);
+ }
+ return (NULL);
+}
+
/*ARGSUSED*/
int
diff --git a/usr/src/lib/libsldap/common/ns_sasl.c b/usr/src/lib/libsldap/common/ns_sasl.c
new file mode 100644
index 0000000000..fc708b735a
--- /dev/null
+++ b/usr/src/lib/libsldap/common/ns_sasl.c
@@ -0,0 +1,580 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <thread.h>
+#include <synch.h>
+#include <sasl/sasl.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <libscf.h>
+#include <libintl.h>
+#include <locale.h>
+#include "ns_sldap.h"
+#include "ns_internal.h"
+
+static int self_gssapi_only = 0;
+static mutex_t self_gssapi_only_lock = DEFAULTMUTEX;
+
+#define DNS_FMRI "svc:/network/dns/client:default"
+#define MSGSIZE 256
+
+#define NSSWITCH_CONF "/etc/nsswitch.conf"
+
+/*
+ * Error Handling
+ */
+#define CLIENT_FPRINTF if (mode_verbose && !mode_quiet) (void) fprintf
+
+/*
+ * One time initializtion
+ */
+int sasl_gssapi_inited = 0;
+static mutex_t sasl_gssapi_lock = DEFAULTMUTEX;
+int
+__s_api_sasl_gssapi_init(void) {
+ int rc = NS_LDAP_SUCCESS;
+ (void) mutex_lock(&sasl_gssapi_lock);
+ if (!sasl_gssapi_inited) {
+ if (getuid() == 0) {
+ if (system(
+ "/usr/sbin/cryptoadm disable metaslot")
+ == 0) {
+ syslog(LOG_WARNING,
+ "libsldap: Metaslot disabled "
+ "for self credential mode");
+ sasl_gssapi_inited = 1;
+ } else {
+ syslog(LOG_ERR,
+ "libsldap: Can't disable "
+ "Metaslot for self credential "
+ "mode");
+ rc = NS_LDAP_INTERNAL;
+ }
+ }
+ }
+ (void) mutex_unlock(&sasl_gssapi_lock);
+
+ return (rc);
+}
+
+/*
+ * nscd calls this function to set self_gssapi_only flag so libsldap performs
+ * sasl/GSSAPI bind only. Also see comments of __ns_ldap_self_gssapi_config.
+ *
+ * Input: flag 0 use any kind of connection
+ * 1 use self/gssapi connection only
+ */
+void
+__ns_ldap_self_gssapi_only_set(int flag) {
+ (void) mutex_lock(&self_gssapi_only_lock);
+ self_gssapi_only = flag;
+ (void) mutex_unlock(&self_gssapi_only_lock);
+}
+/*
+ * Get the flag value of self_gssapi_only
+ */
+int
+__s_api_self_gssapi_only_get(void) {
+ int flag;
+ (void) mutex_lock(&self_gssapi_only_lock);
+ flag = self_gssapi_only;
+ (void) mutex_unlock(&self_gssapi_only_lock);
+ return (flag);
+}
+/*
+ * nscd calls this function to detect the current native ldap configuration.
+ * The output are
+ * NS_LDAP_SELF_GSSAPI_CONFIG_NONE: No credential level self and
+ * no authentication method sasl/GSSAPI is
+ * configured.
+ * NS_LDAP_SELF_GSSAPI_CONFIG_ONLY: Only credential level self and
+ * authentication method sasl/GSSAPI are
+ * configured.
+ * NS_LDAP_SELF_GSSAPI_CONFIG_MIXED: More than one credential level are
+ * configured, including self.
+ * More than one authentication method
+ * are configured, including sasl/GSSAPI.
+ *
+ * __s_api_crosscheck makes sure self and sasl/GSSAPI pair up if they do
+ * get configured.
+ *
+ * When nscd detects it's MIXED case, it calls __ns_ldap_self_gssapi_only_set
+ * to force libsldap to do sasl/GSSAPI bind only for per-user lookup.
+ *
+ * Return: NS_LDAP_SUCCESS
+ * OTHERWISE - FAILURE
+ *
+ * Output: config. See comments above.
+ *
+ */
+int
+__ns_ldap_self_gssapi_config(ns_ldap_self_gssapi_config_t *config) {
+ int self = 0, other_level = 0, gssapi = 0, other_method = 0;
+ ns_auth_t **aMethod = NULL, **aNext = NULL;
+ int **cLevel = NULL, **cNext = NULL, rc;
+ ns_ldap_error_t *errp = NULL;
+
+ if (config == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+ else
+ *config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
+
+ /* Get the credential level list */
+ if ((rc = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
+ (void ***)&cLevel, &errp)) != NS_LDAP_SUCCESS) {
+ if (errp)
+ (void) __ns_ldap_freeError(&errp);
+ if (cLevel)
+ (void) __ns_ldap_freeParam((void ***)&cLevel);
+ return (rc);
+ }
+ if (errp)
+ (void) __ns_ldap_freeError(&errp);
+ /* Get the authentication method list */
+ if ((rc = __ns_ldap_getParam(NS_LDAP_AUTH_P,
+ (void ***)&aMethod, &errp)) != NS_LDAP_SUCCESS) {
+ if (errp)
+ (void) __ns_ldap_freeError(&errp);
+ if (cLevel)
+ (void) __ns_ldap_freeParam((void ***)&cLevel);
+ if (aMethod)
+ (void) __ns_ldap_freeParam((void ***)&aMethod);
+ return (rc);
+ }
+ if (errp)
+ (void) __ns_ldap_freeError(&errp);
+
+ if (cLevel == NULL || aMethod == NULL) {
+ if (cLevel)
+ (void) __ns_ldap_freeParam((void ***)&cLevel);
+ if (aMethod)
+ (void) __ns_ldap_freeParam((void ***)&aMethod);
+ return (NS_LDAP_SUCCESS);
+ }
+
+ for (cNext = cLevel; *cNext != NULL; cNext++) {
+ if (**cNext == NS_LDAP_CRED_SELF)
+ self++;
+ else
+ other_level++;
+ }
+ for (aNext = aMethod; *aNext != NULL; aNext++) {
+ if ((*aNext)->saslmech == NS_LDAP_SASL_GSSAPI)
+ gssapi++;
+ else
+ other_method++;
+ }
+
+ if (self > 0 && gssapi > 0) {
+ if (other_level == 0 && other_method == 0)
+ *config = NS_LDAP_SELF_GSSAPI_CONFIG_ONLY;
+ else
+ *config = NS_LDAP_SELF_GSSAPI_CONFIG_MIXED;
+ }
+
+ if (cLevel)
+ (void) __ns_ldap_freeParam((void ***)&cLevel);
+ if (aMethod)
+ (void) __ns_ldap_freeParam((void ***)&aMethod);
+ return (NS_LDAP_SUCCESS);
+}
+
+int
+__s_api_sasl_bind_callback(
+ /* LINTED E_FUNC_ARG_UNUSED */
+ LDAP *ld,
+ /* LINTED E_FUNC_ARG_UNUSED */
+ unsigned flags,
+ void *defaults,
+ void *in)
+{
+ char *ret = NULL;
+ sasl_interact_t *interact = in;
+ ns_sasl_cb_param_t *cred = (ns_sasl_cb_param_t *)defaults;
+
+
+ while (interact->id != SASL_CB_LIST_END) {
+
+ switch (interact->id) {
+
+ case SASL_CB_GETREALM:
+ ret = cred->realm;
+ break;
+ case SASL_CB_AUTHNAME:
+ ret = cred->authid;
+ break;
+ case SASL_CB_PASS:
+ ret = cred->passwd;
+ break;
+ case SASL_CB_USER:
+ ret = cred->authzid;
+ break;
+ case SASL_CB_NOECHOPROMPT:
+ case SASL_CB_ECHOPROMPT:
+ default:
+ break;
+ }
+
+ if (ret) {
+ interact->result = strdup(ret);
+ if (interact->result == NULL)
+ return (LDAP_NO_MEMORY);
+
+ interact->len = strlen(ret);
+ } else {
+ interact->result = NULL;
+ interact->len = 0;
+ }
+ interact++;
+ }
+
+ return (LDAP_SUCCESS);
+}
+
+/*
+ * Find "dbase: service1 [...] services2" in fname and return
+ * " service1 [...] services2"
+ * e.g.
+ * Find "hosts: files dns" and return " files dns"
+ */
+static char *
+__ns_nsw_getconfig(const char *dbase, const char *fname, int *errp)
+{
+ FILE *fp = NULL;
+ char *linep, *retp = NULL;
+ char lineq[BUFSIZ], db_colon[BUFSIZ];
+
+ if ((fp = fopen(fname, "rF")) == NULL) {
+ *errp = NS_LDAP_CONFIG;
+ return (NULL);
+ }
+ *errp = NS_LDAP_SUCCESS;
+
+ while (linep = fgets(lineq, BUFSIZ, fp)) {
+ char *tokenp, *comment;
+
+ /*
+ * Ignore portion of line following the comment character '#'.
+ */
+ if ((comment = strchr(linep, '#')) != NULL) {
+ *comment = '\0';
+ }
+ if ((*linep == '\0') || isspace(*linep)) {
+ continue;
+ }
+ (void) snprintf(db_colon, BUFSIZ, "%s:", dbase);
+ if ((tokenp = strstr(linep, db_colon)) == NULL) {
+ continue; /* ignore this line */
+ } else {
+ /* skip "dbase:" */
+ retp = strdup(tokenp + strlen(db_colon));
+ if (retp == NULL)
+ *errp = NS_LDAP_MEMORY;
+ }
+ }
+
+ (void) fclose(fp);
+ return (retp);
+}
+/*
+ * Test the configurations of the "hosts" and "ipnodes"
+ * dns has to be present and appear before ldap
+ * e.g.
+ * "dns" , "dns files" "dns ldap files", "files dns" are allowed.
+ *
+ * Kerberos requires dns or it'd fail.
+ */
+static int
+test_dns_nsswitch(int foreground,
+ const char *fname,
+ ns_ldap_error_t **errpp) {
+ int ldap, dns, i, pserr, rc = NS_LDAP_SUCCESS;
+ char *db[3] = {"hosts", "ipnodes", NULL};
+ char buf[MSGSIZE], *conf = NULL, *token = NULL, *last = NULL;
+
+ for (i = 0; db[i] != NULL; i++) {
+ conf = __ns_nsw_getconfig(db[i], fname, &pserr);
+
+ if (conf == NULL) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("Parsing %s to find \"%s:\" "
+ "failed. err: %d"),
+ fname, db[i], pserr);
+ if (foreground) {
+ (void) fprintf(stderr, "%s\n", buf);
+ } else {
+ MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
+ strdup(buf), NS_LDAP_MEMORY);
+ }
+ return (pserr);
+ }
+ ldap = dns = 0;
+ token = strtok_r(conf, " ", &last);
+ while (token != NULL) {
+ if (strncmp(token, "dns", 3) == 0) {
+ if (ldap) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: ldap can't appear "
+ "before dns"), db[i]);
+ if (foreground) {
+ (void) fprintf(stderr,
+ "start: %s\n",
+ buf);
+ } else {
+ MKERROR(LOG_ERR, *errpp,
+ NS_LDAP_CONFIG,
+ strdup(buf),
+ NS_LDAP_MEMORY);
+ }
+ free(conf);
+ return (NS_LDAP_CONFIG);
+ } else {
+ dns++;
+ }
+ } else if (strncmp(token, "ldap", 4) == 0) {
+ ldap++;
+ }
+ /* next token */
+ token = strtok_r(NULL, " ", &last);
+ }
+ if (conf) {
+ free(conf);
+ conf = NULL;
+ }
+ if (!dns) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: dns is not defined in "
+ "%s"), db[i], fname);
+ if (foreground) {
+ (void) fprintf(stderr, "start: %s\n", buf);
+ } else {
+ MKERROR(LOG_ERR, *errpp, NS_LDAP_CONFIG,
+ strdup(buf), NS_LDAP_MEMORY);
+ }
+ rc = NS_LDAP_CONFIG;
+ break;
+ }
+ }
+ return (rc);
+}
+
+static boolean_t
+is_service(const char *fmri, const char *state) {
+ char *st;
+ boolean_t result = B_FALSE;
+
+ if ((st = smf_get_state(fmri)) != NULL) {
+ if (strcmp(st, state) == 0)
+ result = B_TRUE;
+ free(st);
+ }
+ return (result);
+}
+
+
+/*
+ * This function checks dns prerequisites for sasl/GSSAPI bind.
+ * It's called only if config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY ||
+ * config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED.
+ */
+int
+__ns_ldap_check_dns_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ const char *fname,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp) {
+
+ char buf[MSGSIZE];
+ int retcode = NS_LDAP_SUCCESS;
+ int loglevel;
+
+ if (errpp)
+ *errpp = NULL;
+ else
+ return (NS_LDAP_INVALID_PARAM);
+
+ if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
+ /* Shouldn't happen. Check this value just in case */
+ return (NS_LDAP_SUCCESS);
+
+ if ((retcode = test_dns_nsswitch(foreground, fname, errpp)) !=
+ NS_LDAP_SUCCESS)
+ return (retcode);
+
+ if (is_service(DNS_FMRI, SCF_STATE_STRING_ONLINE)) {
+ if (foreground) {
+ CLIENT_FPRINTF(stdout, "start: %s\n",
+ gettext("DNS client is enabled"));
+ } else {
+ syslog(LOG_INFO, "%s",
+ gettext("DNS client is enabled"));
+ }
+ return (NS_LDAP_SUCCESS);
+ } else {
+ if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: DNS client is not enabled. "
+ "Run \"svcadm enable %s\". %s."),
+ "Error", DNS_FMRI, "Abort");
+ loglevel = LOG_ERR;
+ retcode = NS_LDAP_CONFIG;
+ } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: DNS client is not enabled. "
+ "Run \"svcadm enable %s\". %s."
+ "Fall back to other cred level/bind. "),
+ "Warning", DNS_FMRI, "Continue");
+ loglevel = LOG_INFO;
+ retcode = NS_LDAP_SUCCESS;
+ }
+
+ if (foreground) {
+ (void) fprintf(stderr, "start: %s\n", buf);
+ } else {
+ MKERROR(loglevel, *errpp, retcode, strdup(buf),
+ NS_LDAP_MEMORY);
+ }
+ return (retcode);
+ }
+}
+
+/*
+ * Check if sasl/GSSAPI works
+ */
+int
+__ns_ldap_check_gssapi_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp) {
+
+ int rc;
+ char *attr[2] = {"dn", NULL}, buf[MSGSIZE];
+ ns_cred_t cred;
+ ns_ldap_result_t *result = NULL;
+ int loglevel;
+
+ if (errpp)
+ *errpp = NULL;
+ else
+ return (NS_LDAP_INVALID_PARAM);
+
+ if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
+ /* Don't need to check */
+ return (NS_LDAP_SUCCESS);
+
+ (void) memset(&cred, 0, sizeof (ns_cred_t));
+
+ cred.auth.type = NS_LDAP_AUTH_SASL;
+ cred.auth.tlstype = NS_LDAP_TLS_NONE;
+ cred.auth.saslmech = NS_LDAP_SASL_GSSAPI;
+
+ rc = __ns_ldap_list(NULL, (const char *)"objectclass=*",
+ NULL, (const char **)attr, &cred,
+ NS_LDAP_SCOPE_BASE, &result, errpp, NULL, NULL);
+ if (result)
+ (void) __ns_ldap_freeResult(&result);
+
+ if (rc == NS_LDAP_SUCCESS) {
+ if (foreground) {
+ CLIENT_FPRINTF(stdout, "start: %s\n",
+ gettext("sasl/GSSAPI bind works"));
+ } else {
+ syslog(LOG_INFO, "%s",
+ gettext("sasl/GSSAPI bind works"));
+ }
+ return (NS_LDAP_SUCCESS);
+ } else {
+ if (config == NS_LDAP_SELF_GSSAPI_CONFIG_ONLY) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: sasl/GSSAPI bind is not "
+ "working. %s."),
+ "Error", "Abort");
+ loglevel = LOG_ERR;
+ } else if (config == NS_LDAP_SELF_GSSAPI_CONFIG_MIXED) {
+ (void) snprintf(buf, MSGSIZE,
+ gettext("%s: sasl/GSSAPI bind is not "
+ "working. Fall back to other cred "
+ "level/bind. %s."),
+ "Warning", "Continue");
+ loglevel = LOG_INFO;
+ /* reset return code */
+ rc = NS_LDAP_SUCCESS;
+ }
+
+ if (foreground) {
+ (void) fprintf(stderr, "start: %s\n", buf);
+ } else {
+ MKERROR(loglevel, *errpp, rc, strdup(buf),
+ NS_LDAP_MEMORY);
+ }
+ return (rc);
+ }
+}
+/*
+ * This is called by ldap_cachemgr to check dns and gssapi prequisites.
+ */
+int
+__ns_ldap_check_all_preq(int foreground,
+ int mode_verbose,
+ int mode_quiet,
+ ns_ldap_self_gssapi_config_t config,
+ ns_ldap_error_t **errpp) {
+
+ int rc;
+
+ if (errpp)
+ *errpp = NULL;
+ else
+ return (NS_LDAP_INVALID_PARAM);
+
+ if (config == NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
+ /* Don't need to check */
+ return (NS_LDAP_SUCCESS);
+
+ if ((rc = __ns_ldap_check_dns_preq(foreground,
+ mode_verbose, mode_quiet, NSSWITCH_CONF,
+ config, errpp)) != NS_LDAP_SUCCESS)
+ return (rc);
+ if ((rc = __ns_ldap_check_gssapi_preq(foreground,
+ mode_verbose, mode_quiet, config, errpp)) !=
+ NS_LDAP_SUCCESS)
+ return (rc);
+
+ return (NS_LDAP_SUCCESS);
+}
diff --git a/usr/src/lib/libsldap/common/ns_sldap.h b/usr/src/lib/libsldap/common/ns_sldap.h
index 0138c1e3d5..59d7ae516a 100644
--- a/usr/src/lib/libsldap/common/ns_sldap.h
+++ b/usr/src/lib/libsldap/common/ns_sldap.h
@@ -91,7 +91,7 @@ typedef enum ScopeType {
typedef enum CredLevel {
NS_LDAP_CRED_ANON = 0,
NS_LDAP_CRED_PROXY = 1,
- NS_LDAP_CRED_SELF = 2 /* currently not supported */
+ NS_LDAP_CRED_SELF = 2
} CredLevel_t;
typedef enum AuthType {
@@ -113,14 +113,14 @@ typedef enum SaslMech {
NS_LDAP_SASL_CRAM_MD5 = 1,
NS_LDAP_SASL_DIGEST_MD5 = 2,
NS_LDAP_SASL_EXTERNAL = 3, /* currently not supported */
- NS_LDAP_SASL_GSSAPI = 4, /* currently not supported */
+ NS_LDAP_SASL_GSSAPI = 4,
NS_LDAP_SASL_SPNEGO = 5 /* currently not supported */
} SaslMech_t;
typedef enum SaslOpt {
NS_LDAP_SASLOPT_NONE = 0,
- NS_LDAP_SASLOPT_INT = 1, /* currently not supported */
- NS_LDAP_SASLOPT_PRIV = 2 /* currently not supported */
+ NS_LDAP_SASLOPT_INT = 1,
+ NS_LDAP_SASLOPT_PRIV = 2
} SaslOpt_t;
typedef enum PrefOnly {
@@ -211,6 +211,17 @@ typedef enum {
} ParamIndexType;
/*
+ * NONE - No self / SASL/GSSAPI configured
+ * ONLY - Only self / SASL/GSSAPI configured
+ * MIXED - self / SASL/GSSAPI is mixed with other types of configuration
+ */
+typedef enum {
+ NS_LDAP_SELF_GSSAPI_CONFIG_NONE = 0,
+ NS_LDAP_SELF_GSSAPI_CONFIG_ONLY = 1,
+ NS_LDAP_SELF_GSSAPI_CONFIG_MIXED = 2
+} ns_ldap_self_gssapi_config_t;
+
+/*
* __ns_ldap_*() return codes
*/
typedef enum {
@@ -614,6 +625,10 @@ char **__ns_ldap_getAttr(
const ns_ldap_entry_t *entry,
const char *attrname);
+ns_ldap_attr_t *__ns_ldap_getAttrStruct(
+ const ns_ldap_entry_t *entry,
+ const char *attrname);
+
int __ns_ldap_getServiceAuthMethods(
const char *service,
ns_auth_t ***auth,
@@ -666,6 +681,12 @@ int __ns_ldap_getParamType(
int __ns_ldap_getAcctMgmt(
const char *user,
AcctUsableResponse_t *acctResp);
+void
+__ns_ldap_self_gssapi_only_set(
+ int flag);
+int
+__ns_ldap_self_gssapi_config(
+ ns_ldap_self_gssapi_config_t *config);
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libsldap/common/ns_writes.c b/usr/src/lib/libsldap/common/ns_writes.c
index dadec06207..474db98161 100644
--- a/usr/src/lib/libsldap/common/ns_writes.c
+++ b/usr/src/lib/libsldap/common/ns_writes.c
@@ -691,7 +691,7 @@ write_state_machine(
switch (state) {
case W_EXIT:
if (connectionId > -1)
- DropConnection(connectionId, 0);
+ DropConnection(connectionId, NS_LDAP_NEW_CONN);
if (ref_list)
__s_api_deleteRefInfo(ref_list);
if (target_dn && target_dn_allocated)
@@ -723,7 +723,7 @@ write_state_machine(
break;
case GET_CONNECTION:
rc = __s_api_getConnection(NULL,
- flags,
+ flags | NS_LDAP_NEW_CONN,
cred,
&connectionId,
&conp,
@@ -912,7 +912,7 @@ write_state_machine(
if (*errorp)
(void) __ns_ldap_freeError(errorp);
if (connectionId > -1)
- DropConnection(connectionId, 0);
+ DropConnection(connectionId, NS_LDAP_NEW_CONN);
rc = __s_api_getConnection(current_ref->refHost,
0,
cred,
diff --git a/usr/src/lib/libsldap/req.flg b/usr/src/lib/libsldap/req.flg
index 6ced3afe87..25da177a24 100644
--- a/usr/src/lib/libsldap/req.flg
+++ b/usr/src/lib/libsldap/req.flg
@@ -28,3 +28,4 @@
echo_file usr/src/lib/libldap5/include/ldap/solaris-priv.h
echo_file usr/src/lib/libldap5/include/ldap/ldappr.h
+echo_file usr/src/lib/libldap5/include/ldap/solaris-int.h
diff --git a/usr/src/lib/libsocket/common/mapfile-vers b/usr/src/lib/libsocket/common/mapfile-vers
index 81c0972716..c4fdda3f62 100644
--- a/usr/src/lib/libsocket/common/mapfile-vers
+++ b/usr/src/lib/libsocket/common/mapfile-vers
@@ -140,6 +140,15 @@ SUNWprivate_1.3 {
global:
_link_aton;
_link_ntoa;
+ _nss_initf_ethers;
+ _nss_initf_net;
+ _nss_initf_netmasks;
+ _nss_initf_proto;
+ _nss_initf_services;
+ str2ether;
+ str2addr;
+ str2netent;
+ str2protoent;
} SUNWprivate_1.2;
SUNWprivate_1.2 {
diff --git a/usr/src/lib/libsocket/inet/ether_addr.c b/usr/src/lib/libsocket/inet/ether_addr.c
index 3fbdb3bbb0..44f8979691 100644
--- a/usr/src/lib/libsocket/inet/ether_addr.c
+++ b/usr/src/lib/libsocket/inet/ether_addr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -61,11 +60,11 @@
#include <netinet/if_ether.h>
#include <nss_dbdefs.h>
-static int str2ether(const char *, int, void *, char *, int);
+int str2ether(const char *, int, void *, char *, int);
static DEFINE_NSS_DB_ROOT(db_root);
-static void
+void
_nss_initf_ethers(nss_db_params_t *p)
{
p->name = NSS_DBNAM_ETHERS;
@@ -181,7 +180,7 @@ ether_line(
#define lisalnum(x) (isdigit(x) || \
((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
/* ARGSUSED */
-static int
+int
str2ether(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
{
uchar_t *ether = (uchar_t *)ent;
diff --git a/usr/src/lib/libsocket/inet/getnetent_r.c b/usr/src/lib/libsocket/inet/getnetent_r.c
index 1484809b15..0b9ae98556 100644
--- a/usr/src/lib/libsocket/inet/getnetent_r.c
+++ b/usr/src/lib/libsocket/inet/getnetent_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1986-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,7 +36,7 @@
#include <nss_dbdefs.h>
-static int str2netent(const char *, int, void *, char *, int);
+int str2netent(const char *, int, void *, char *, int);
static int net_stayopen;
/*
@@ -48,7 +47,7 @@ static int net_stayopen;
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
-static void
+void
_nss_initf_net(nss_db_params_t *p)
{
p->name = NSS_DBNAM_NETWORKS;
@@ -62,6 +61,10 @@ getnetbyname_r(const char *name, struct netent *result,
nss_XbyY_args_t arg;
nss_status_t res;
+ if (name == (const char *)NULL) {
+ errno = ERANGE;
+ return (NULL);
+ }
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2netent);
arg.key.name = name;
arg.stayopen = net_stayopen;
@@ -127,7 +130,7 @@ getnetent_r(struct netent *result, char *buffer, int buflen)
* wherein the field pointers would be set to areas in the buffer if
* need be. instring and buffer should be separate areas.
*/
-static int
+int
str2netent(const char *instr, int lenstr,
void *ent /* really (struct netnet *) */, char *buffer, int buflen)
{
diff --git a/usr/src/lib/libsocket/inet/getprotoent_r.c b/usr/src/lib/libsocket/inet/getprotoent_r.c
index e1cb1c7f0b..4f89a047bf 100644
--- a/usr/src/lib/libsocket/inet/getprotoent_r.c
+++ b/usr/src/lib/libsocket/inet/getprotoent_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1986-1992 by Sun Microsystems Inc.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -31,7 +31,7 @@
#include <string.h>
#include <nss_dbdefs.h>
-static int str2protoent(const char *, int, void *,
+int str2protoent(const char *, int, void *,
char *, int);
static int proto_stayopen;
@@ -43,7 +43,7 @@ static int proto_stayopen;
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
-static void
+void
_nss_initf_proto(nss_db_params_t *p)
{
p->name = NSS_DBNAM_PROTOCOLS;
@@ -57,6 +57,10 @@ getprotobyname_r(const char *name, struct protoent *result,
nss_XbyY_args_t arg;
nss_status_t res;
+ if (name == (const char *)NULL) {
+ errno = ERANGE;
+ return (NULL);
+ }
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent);
arg.key.name = name;
arg.stayopen = proto_stayopen;
@@ -121,7 +125,7 @@ getprotoent_r(struct protoent *result, char *buffer, int buflen)
* need be. instring and buffer should be separate areas. Let's not
* fight over crumbs.
*/
-static int
+int
str2protoent(const char *instr, int lenstr,
void *ent /* it is really (struct protoent *) */,
char *buffer, int buflen)
diff --git a/usr/src/lib/libsocket/inet/getservent_r.c b/usr/src/lib/libsocket/inet/getservent_r.c
index 6eb9ff49a2..aeccf9f499 100644
--- a/usr/src/lib/libsocket/inet/getservent_r.c
+++ b/usr/src/lib/libsocket/inet/getservent_r.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1986-1994 by Sun Microsystems Inc.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* lib/libsocket/inet/getservent_r.c
*
@@ -52,7 +52,7 @@ static int services_stayopen;
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
-static void
+void
_nss_initf_services(nss_db_params_t *p)
{
p->name = NSS_DBNAM_SERVICES;
diff --git a/usr/src/lib/libsocket/inet/netmasks.c b/usr/src/lib/libsocket/inet/netmasks.c
index e944e00e84..f9e5ef4049 100644
--- a/usr/src/lib/libsocket/inet/netmasks.c
+++ b/usr/src/lib/libsocket/inet/netmasks.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,11 +43,11 @@
#include <arpa/inet.h>
#include <nss_dbdefs.h>
-static int str2addr(const char *, int, void *, char *, int);
+int str2addr(const char *, int, void *, char *, int);
static DEFINE_NSS_DB_ROOT(db_root);
-static void
+void
_nss_initf_netmasks(nss_db_params_t *p)
{
p->name = NSS_DBNAM_NETMASKS;
@@ -59,24 +58,27 @@ _nss_initf_netmasks(nss_db_params_t *p)
* Print a network number such as 129.144 as well as an IP address.
* Assumes network byte order for both IP addresses and network numbers
* (Network numbers are normally passed around in host byte order).
+ * to be MT safe, use a passed in buffer like otherget*_r APIs.
*/
static char *
-inet_nettoa(struct in_addr in)
+inet_nettoa(struct in_addr in, char *result, int len)
{
uint32_t addr = in.s_addr;
uchar_t *up = (uchar_t *)&addr;
- static char result[256];
+
+ if (result == NULL)
+ return (NULL);
/* Omit leading zeros */
if (up[0]) {
- (void) sprintf(result, "%d.%d.%d.%d",
+ (void) snprintf(result, len, "%d.%d.%d.%d",
up[0], up[1], up[2], up[3]);
} else if (up[1]) {
- (void) sprintf(result, "%d.%d.%d", up[1], up[2], up[3]);
+ (void) snprintf(result, len, "%d.%d.%d", up[1], up[2], up[3]);
} else if (up[2]) {
- (void) sprintf(result, "%d.%d", up[2], up[3]);
+ (void) snprintf(result, len, "%d.%d", up[2], up[3]);
} else {
- (void) sprintf(result, "%d", up[3]);
+ (void) snprintf(result, len, "%d", up[3]);
}
return (result);
}
@@ -102,8 +104,10 @@ getnetmaskbykey(const struct in_addr addr, struct in_addr *mask)
* the network address in the 'name' field as a filter to speed
* up the lookup.
*/
+ if (inet_nettoa(addr, tmp, NSS_LINELEN_NETMASKS) == NULL)
+ return (NSS_NOTFOUND);
+
NSS_XbyY_INIT(&arg, mask, NULL, 0, str2addr);
- (void) strcpy(tmp, inet_nettoa(addr));
arg.key.name = tmp;
res = nss_search(&db_root, _nss_initf_netmasks,
NSS_DBOP_NETMASKS_BYNET, &arg);
diff --git a/usr/src/lib/nsswitch/compat/common/compat_common.c b/usr/src/lib/nsswitch/compat/common/compat_common.c
index fe21797abf..330a4b7707 100644
--- a/usr/src/lib/nsswitch/compat/common/compat_common.c
+++ b/usr/src/lib/nsswitch/compat/common/compat_common.c
@@ -36,6 +36,11 @@
#include <ctype.h>
#include <bsm/libbsm.h>
#include <user_attr.h>
+#include <pwd.h>
+#include <shadow.h>
+#include <grp.h>
+#include <unistd.h> /* for GF_PATH */
+#include <dlfcn.h>
#include "compat_common.h"
/*
@@ -44,6 +49,62 @@
extern int yp_get_default_domain(char **domain);
+/* from libc */
+extern int str2passwd(const char *instr, int lenstr, void *ent,
+ char *buffer, int buflen);
+extern int str2spwd(const char *instr, int lenstr, void *ent,
+ char *buffer, int buflen);
+extern int str2group(const char *instr, int lenstr, void *ent,
+ char *buffer, int buflen);
+
+/* from libnsl */
+extern char *_strtok_escape(char *, char *, char **);
+
+/*
+ * str2auuser_s and str2userattr_s are very simple version
+ * of the str2auuser() and str2userattr() that can be found in
+ * libnsl. They only copy the user name into the userstr_t
+ * or au_user_str_t structure (so check on user name can be
+ * performed).
+ */
+static int
+str2auuser_s(
+ const char *instr,
+ int lenstr,
+ void *ent,
+ char *buffer,
+ int buflen)
+{
+ char *last = NULL;
+ char *sep = KV_TOKEN_DELIMIT;
+ au_user_str_t *au_user = (au_user_str_t *)ent;
+
+ if (lenstr >= buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) strncpy(buffer, instr, buflen);
+ au_user->au_name = _strtok_escape(buffer, sep, &last);
+ return (0);
+}
+
+static int
+str2userattr_s(
+ const char *instr,
+ int lenstr,
+ void *ent,
+ char *buffer,
+ int buflen)
+{
+ char *last = NULL;
+ char *sep = KV_TOKEN_DELIMIT;
+ userstr_t *user = (userstr_t *)ent;
+
+ if (lenstr >= buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) strncpy(buffer, instr, buflen);
+ user->name = _strtok_escape(buffer, sep, &last);
+ return (0);
+}
+
/*
* Routines to manage list of "-" users for get{pw, sp, gr}ent(). Current
* implementation is completely moronic; we use a linked list. But then
@@ -58,7 +119,6 @@ struct setofstrings {
* object rather than two.
*/
};
-typedef struct setofstrings *strset_t;
static void
strset_free(ssp)
@@ -88,7 +148,7 @@ strset_add(ssp, nam)
free(new);
return (B_FALSE);
}
- strcpy(new->name, nam);
+ (void) strcpy(new->name, nam);
new->next = *ssp;
*ssp = new;
return (B_TRUE);
@@ -109,41 +169,6 @@ strset_in(ssp, nam)
return (B_FALSE);
}
-
-struct compat_backend {
- compat_backend_op_t *ops;
- int n_ops;
- const char *filename;
- FILE *f;
- int minbuf;
- char *buf;
- int linelen; /* <== Explain use, lifetime */
-
- nss_db_initf_t db_initf;
- nss_db_root_t *db_rootp; /* Shared between instances */
- nss_getent_t db_context; /* Per-instance enumeration */
-
- compat_get_name getnamef;
- compat_merge_func mergef;
-
- /* We wouldn't need all this hokey state stuff if we */
- /* used another thread to implement a coroutine... */
- enum {
- GETENT_FILE,
- GETENT_NETGROUP,
- GETENT_ATTRDB,
- GETENT_ALL,
- GETENT_DONE
- } state;
- strset_t minuses;
-
- int permit_netgroups;
- const char *yp_domain;
- nss_backend_t *getnetgrent_backend;
- char *netgr_buffer;
-};
-
-
/*
* Lookup and enumeration routines for +@group and -@group.
*
@@ -171,15 +196,6 @@ netgr_in(compat_backend_ptr_t be, const char *group, const char *user)
return (innetgr(group, 0, user, be->yp_domain));
}
-static boolean_t
-netgr_all_in(compat_backend_ptr_t be, const char *group)
-{
- /*
- * 4.x does this; ours not to reason why...
- */
- return (netgr_in(be, group, "*"));
-}
-
static void
netgr_set(be, netgroup)
compat_backend_ptr_t be;
@@ -202,7 +218,7 @@ netgr_set(be, netgroup)
args.netgroup = netgroup;
args.iterator = 0;
- nss_search(&netgr_db_root, _nss_initf_netgroup,
+ (void) nss_search(&netgr_db_root, _nss_initf_netgroup,
NSS_DBOP_NETGROUP_SET, &args);
be->getnetgrent_backend = args.iterator;
}
@@ -270,7 +286,7 @@ do_merge(be, args, instr, linelen)
int overrides;
const char *p;
const char *end = instr + linelen;
- nss_status_t res;
+ nss_status_t res = NSS_NOTFOUND;
/*
* Potential optimization: only perform the field-splitting nonsense
@@ -292,7 +308,7 @@ do_merge(be, args, instr, linelen)
overrides = -1; /* Indicates "you lose" */
break;
}
- memcpy(s, p, len);
+ (void) memcpy(s, p, len);
s[len] = '\0';
fields[i] = s;
overrides++;
@@ -306,16 +322,29 @@ do_merge(be, args, instr, linelen)
}
}
if (overrides == 1) {
- /* No real overrides, return (*args) intact */
- res = NSS_SUCCESS;
- } else if (overrides > 1) {
+ /*
+ * return result here if /etc file format is requested
+ */
+ if (be->return_string_data != 1) {
+ /* No real overrides, return (*args) intact */
+ res = NSS_SUCCESS;
+ } else {
+ free(fields[0]);
+ fields[0] = NULL;
+ }
+ }
+
+ if (overrides > 1 || be->return_string_data == 1) {
/*
* The zero'th field is always nonempty (+/-...), but at least
* one other field was also nonempty, i.e. wants to override
*/
switch ((*be->mergef)(be, args, (const char **)fields)) {
case NSS_STR_PARSE_SUCCESS:
- args->returnval = args->buf.result;
+ if (be->return_string_data != 1)
+ args->returnval = args->buf.result;
+ else
+ args->returnval = args->buf.buffer;
args->erange = 0;
res = NSS_SUCCESS;
break;
@@ -331,7 +360,7 @@ do_merge(be, args, instr, linelen)
res = NSS_NOTFOUND;
break;
}
- } else {
+ } else if (res != NSS_SUCCESS) {
args->returnval = 0;
args->erange = 0;
res = NSS_UNAVAIL; /* ==> Right? */
@@ -383,7 +412,7 @@ _nss_compat_endent(be, dummy)
void *dummy;
{
if (be->f != 0) {
- fclose(be->f);
+ (void) fclose(be->f);
be->f = 0;
}
if (be->buf != 0) {
@@ -412,7 +441,7 @@ _nss_compat_destr(be, dummy)
{
if (be != 0) {
if (be->f != 0) {
- _nss_compat_endent(be, 0);
+ (void) _nss_compat_endent(be, 0);
}
nss_delete(be->db_rootp);
nss_delete(&netgr_db_root);
@@ -459,6 +488,7 @@ read_line(f, buffer, buflen)
;
}
}
+ /*NOTREACHED*/
}
static int
@@ -493,6 +523,10 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num)
int (*func)();
const char *filter = argp->key.name;
nss_status_t res;
+ union {
+ au_user_str_t au;
+ userstr_t user;
+ } workarea;
#ifdef DEBUG
(void) fprintf(stdout, "\n[compat_common.c: _attrdb_compat_XY_all]\n");
@@ -502,11 +536,33 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num)
(be->buf = malloc(be->minbuf)) == 0) {
return (NSS_UNAVAIL);
}
- if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) {
- return (res);
- }
+ if (check != NULL)
+ if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS)
+ return (res);
+
res = NSS_NOTFOUND;
+ /*
+ * assume a NULL buf.result pointer is an indication
+ * that the lookup result should be returned in /etc
+ * file format
+ */
+ if (argp->buf.result == NULL) {
+ be->return_string_data = 1;
+
+ /*
+ * the code executed later needs the result struct
+ * as working area
+ */
+ argp->buf.result = &workarea;
+
+ if (strcmp(be->filename, USERATTR_FILENAME) == 0)
+ func = str2userattr_s;
+ else
+ func = str2auuser_s;
+ } else
+ func = argp->str2ent;
+
/*CONSTCOND*/
while (1) {
int linelen;
@@ -560,16 +616,36 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num)
}
}
argp->returnval = 0;
- func = argp->str2ent;
parsestat = (*func)(instr, linelen, argp->buf.result,
argp->buf.buffer, argp->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
- argp->returnval = argp->buf.result;
+ argp->returnval = argp->buf.result;
if (check == 0 || (*check)(argp)) {
+ int len;
+
+ if (be->return_string_data != 1) {
+ res = NSS_SUCCESS;
+ break;
+ }
+
+ /* copy string data to result buffer */
+ argp->buf.result = NULL;
+ argp->returnval = argp->buf.buffer;
+ if ((len = strlcpy(argp->buf.buffer, instr,
+ argp->buf.buflen)) >=
+ argp->buf.buflen) {
+ argp->returnval = NULL;
+ res = NSS_NOTFOUND;
+ argp->erange = 1;
+ break;
+ }
+
+ argp->returnlen = len;
res = NSS_SUCCESS;
break;
}
} else if (parsestat == NSS_STR_PARSE_ERANGE) {
+ res = NSS_NOTFOUND;
argp->erange = 1;
break;
}
@@ -583,6 +659,14 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num)
}
if (res != NSS_SUCCESS) {
+ /*
+ * tell the nss_search() and nss_getent() below
+ * if the result should be returned in the /etc
+ * file format
+ */
+ if (be->return_string_data == 1)
+ argp->buf.result = NULL;
+
if ((op_num == NSS_DBOP_USERATTR_BYNAME) ||
(op_num == NSS_DBOP_AUDITUSER_BYNAME)) {
res = nss_search(be->db_rootp,
@@ -611,6 +695,13 @@ _nss_compat_XY_all(be, args, check, op_num)
{
nss_status_t res;
int parsestat;
+ union {
+ struct passwd pwd;
+ struct spwd shdw;
+ struct group grp;
+ } workarea;
+ int (*str2ent_save)();
+
if (be->buf == 0 &&
(be->buf = malloc(be->minbuf)) == 0) {
@@ -623,6 +714,30 @@ _nss_compat_XY_all(be, args, check, op_num)
res = NSS_NOTFOUND;
+ /*
+ * assume a NULL buf.result pointer is an indication
+ * that the lookup result should be returned in /etc
+ * file format
+ */
+ if (args->buf.result == NULL) {
+
+ be->return_string_data = 1;
+
+ /*
+ * the code executed later needs the result struct
+ * as working area
+ */
+ args->buf.result = &workarea;
+
+ str2ent_save = args->str2ent;
+ if (strcmp(be->filename, PASSWD) == 0)
+ args->str2ent = str2passwd;
+ else if (strcmp(be->filename, SHADOW) == 0)
+ args->str2ent = str2spwd;
+ else
+ args->str2ent = str2group;
+ }
+
/*CONSTCOND*/
while (1) {
int linelen;
@@ -648,13 +763,37 @@ _nss_compat_XY_all(be, args, check, op_num)
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = args->buf.result;
if ((*check)(args) != 0) {
- res = NSS_SUCCESS;
- break;
- }
+ int len;
+ if (be->return_string_data != 1) {
+ res = NSS_SUCCESS;
+ break;
+ }
+
+ /*
+ * copy string data to
+ * result buffer
+ */
+ args->buf.result = NULL;
+ args->str2ent = str2ent_save;
+ if ((len = strlcpy(args->buf.buffer,
+ instr, args->buf.buflen)) >=
+ args->buf.buflen)
+ parsestat =
+ NSS_STR_PARSE_ERANGE;
+ else {
+ args->returnval =
+ args->buf.buffer;
+ args->returnlen = len;
+ res = NSS_SUCCESS;
+ break;
+ }
+ } else
+ continue;
+ }
/* ===> Check the Dani logic here... */
- } else if (parsestat == NSS_STR_PARSE_ERANGE) {
+ if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
res = NSS_NOTFOUND;
break;
@@ -665,6 +804,7 @@ _nss_compat_XY_all(be, args, check, op_num)
/* ==> ?? */ continue;
}
+
/*
* Process "+", "+name", "+@netgroup", "-name" or "-@netgroup"
*
@@ -701,15 +841,15 @@ _nss_compat_XY_all(be, args, check, op_num)
continue;
if (instr[0] == '+') {
/* need to search for "+" entry */
- nss_search(be->db_rootp, be->db_initf,
- op_num, args);
+ (void) nss_search(be->db_rootp,
+ be->db_initf, op_num, args);
if (args->returnval == 0)
continue;
}
} else {
/* search then compare */
- nss_search(be->db_rootp, be->db_initf, op_num,
- args);
+ (void) nss_search(be->db_rootp,
+ be->db_initf, op_num, args);
if (args->returnval == 0)
continue;
if (!be->permit_netgroups ||
@@ -727,7 +867,8 @@ _nss_compat_XY_all(be, args, check, op_num)
if (instr[0] == '-')
continue;
/* need to search for "+" entry */
- nss_search(be->db_rootp, be->db_initf, op_num, args);
+ (void) nss_search(be->db_rootp, be->db_initf,
+ op_num, args);
if (args->returnval == 0)
continue;
} else {
@@ -746,15 +887,15 @@ _nss_compat_XY_all(be, args, check, op_num)
continue;
if (instr[0] == '+') {
/* need to search for "+" entry */
- nss_search(be->db_rootp, be->db_initf,
- op_num, args);
+ (void) nss_search(be->db_rootp,
+ be->db_initf, op_num, args);
if (args->returnval == 0)
continue;
}
} else {
/* search then compare */
- nss_search(be->db_rootp, be->db_initf, op_num,
- args);
+ (void) nss_search(be->db_rootp,
+ be->db_initf, op_num, args);
if (args->returnval == 0)
continue;
if (strcmp(instr + 1, (*be->getnamef)(args))
@@ -783,6 +924,10 @@ _nss_compat_XY_all(be, args, check, op_num)
(void) _nss_compat_endent(be, 0);
}
+ if (be->return_string_data == 1) {
+ args->str2ent = str2ent_save;
+ }
+
return (res);
}
@@ -794,6 +939,12 @@ _nss_compat_getent(be, a)
nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
nss_status_t res;
char *colon = 0; /* <=== need comment re lifetime */
+ union {
+ struct passwd pwd;
+ struct spwd shdw;
+ struct group grp;
+ } workarea;
+
if (be->f == 0) {
if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) {
@@ -806,6 +957,21 @@ _nss_compat_getent(be, a)
return (NSS_UNAVAIL); /* really panic, malloc failed */
}
+ /*
+ * assume a NULL buf.result pointer is an indication
+ * that the lookup result should be returned in /etc
+ * file format
+ */
+ if (args->buf.result == NULL) {
+ be->return_string_data = 1;
+
+ /*
+ * the code executed later needs the result struct
+ * as working area
+ */
+ args->buf.result = &workarea;
+ }
+
/*CONSTCOND*/
while (1) {
char *instr = be->buf;
@@ -829,6 +995,7 @@ _nss_compat_getent(be, a)
return (NSS_NOTFOUND);
case GETENT_ATTRDB:
+ args->key.name = NULL;
res = _attrdb_compat_XY_all(be,
args, 1, (compat_XY_check_func)NULL, 0);
return (res);
@@ -845,11 +1012,12 @@ _nss_compat_getent(be, a)
}
if (instr[0] == '-') {
if (instr[1] != '@') {
- strset_add(&be->minuses, instr + 1);
+ (void) strset_add(&be->minuses,
+ instr + 1);
} else if (be->permit_netgroups) {
netgr_set(be, instr + 2);
while (netgr_next_u(be, &name)) {
- strset_add(&be->minuses,
+ (void) strset_add(&be->minuses,
name);
}
netgr_end(be);
@@ -869,8 +1037,30 @@ _nss_compat_getent(be, a)
args->buf.buffer,
args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
- args->returnval = args->buf.result;
- return (NSS_SUCCESS);
+ int len;
+
+ if (be->return_string_data != 1) {
+ args->returnval =
+ args->buf.result;
+ return (NSS_SUCCESS);
+ }
+
+ /*
+ * copy string data to
+ * result buffer
+ */
+ args->buf.result = NULL;
+ args->returnval =
+ args->buf.buffer;
+ if ((len = strlcpy(args->buf.buffer,
+ instr, args->buf.buflen)) >=
+ args->buf.buflen)
+ parsestat =
+ NSS_STR_PARSE_ERANGE;
+ else {
+ args->returnlen = len;
+ return (NSS_SUCCESS);
+ }
}
/* ==> ?? Treat ERANGE differently ?? */
if (parsestat == NSS_STR_PARSE_ERANGE) {
@@ -903,7 +1093,7 @@ _nss_compat_getent(be, a)
case GETENT_ALL:
linelen = be->linelen;
args->returnval = 0;
- nss_getent(be->db_rootp, be->db_initf,
+ (void) nss_getent(be->db_rootp, be->db_initf,
&be->db_context, args);
if (args->returnval == 0) {
/* ==> ?? Treat ERANGE differently ?? */
@@ -947,7 +1137,7 @@ _nss_compat_getent(be, a)
savename = args->key.name;
args->key.name = name;
args->returnval = 0;
- nss_search(be->db_rootp, be->db_initf,
+ (void) nss_search(be->db_rootp, be->db_initf,
NSS_DBOP_next_iter, args);
args->key.name = savename; /* In case anyone cares */
}
@@ -966,6 +1156,7 @@ _nss_compat_getent(be, a)
}
return (do_merge(be, args, instr, linelen));
}
+ /*NOTREACHED*/
}
/* We don't use this directly; we just copy the bits when we want to */
@@ -1016,6 +1207,7 @@ _nss_compat_constr(ops, n_ops, filename, min_bufsize, rootp, initf, netgroups,
be->yp_domain = 0;
be->getnetgrent_backend = 0;
be->netgr_buffer = 0;
+ be->return_string_data = 0;
return ((nss_backend_t *)be);
}
diff --git a/usr/src/lib/nsswitch/compat/common/compat_common.h b/usr/src/lib/nsswitch/compat/common/compat_common.h
index cfd4f37e5c..08b30a3c82 100644
--- a/usr/src/lib/nsswitch/compat/common/compat_common.h
+++ b/usr/src/lib/nsswitch/compat/common/compat_common.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1992, by Sun Microsystems, Inc.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
* Common code and structures used by name-service-switch "compat" backends.
*/
@@ -58,6 +59,42 @@ typedef int (*compat_merge_func)(compat_backend_ptr_t,
nss_XbyY_args_t *,
const char **fields);
+typedef struct setofstrings *strset_t;
+
+struct compat_backend {
+ compat_backend_op_t *ops;
+ int n_ops;
+ const char *filename;
+ FILE *f;
+ int minbuf;
+ char *buf;
+ int linelen; /* <== Explain use, lifetime */
+
+ nss_db_initf_t db_initf;
+ nss_db_root_t *db_rootp; /* Shared between instances */
+ nss_getent_t db_context; /* Per-instance enumeration */
+
+ compat_get_name getnamef;
+ compat_merge_func mergef;
+
+ /* We wouldn't need all this hokey state stuff if we */
+ /* used another thread to implement a coroutine... */
+ enum {
+ GETENT_FILE,
+ GETENT_NETGROUP,
+ GETENT_ATTRDB,
+ GETENT_ALL,
+ GETENT_DONE
+ } state;
+ strset_t minuses;
+
+ int permit_netgroups;
+ const char *yp_domain;
+ nss_backend_t *getnetgrent_backend;
+ char *netgr_buffer;
+ int return_string_data;
+};
+
#if defined(__STDC__)
extern nss_backend_t *_nss_compat_constr(compat_backend_op_t *ops,
int n_ops,
diff --git a/usr/src/lib/nsswitch/compat/common/getauuser.c b/usr/src/lib/nsswitch/compat/common/getauuser.c
index 8bf983c7dc..55b700bbb4 100644
--- a/usr/src/lib/nsswitch/compat/common/getauuser.c
+++ b/usr/src/lib/nsswitch/compat/common/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -34,7 +33,7 @@
static DEFINE_NSS_DB_ROOT(db_root);
-void
+static void
_nss_initf_auuser_compat(nss_db_params_t *p)
{
p->name = NSS_DBNAM_AUDITUSER;
@@ -91,6 +90,7 @@ static compat_backend_op_t auuser_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_compat_audit_user_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/compat/common/getgrent.c b/usr/src/lib/nsswitch/compat/common/getgrent.c
index b34c594de2..0457392e59 100644
--- a/usr/src/lib/nsswitch/compat/common/getgrent.c
+++ b/usr/src/lib/nsswitch/compat/common/getgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -22,7 +21,7 @@
/*
* getgrent.c
*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* lib/nsswitch/compat/getgrent.c -- name-service-switch backend for getgrnam()
@@ -192,6 +191,7 @@ merge_grents(be, argp, fields)
char *buf;
char *s;
int parsestat;
+ int dlen;
/*
* We're allowed to override the passwd (has anyone ever actually used
@@ -201,7 +201,8 @@ merge_grents(be, argp, fields)
*
* Efficiency is heartlessly abandoned in the quest for simplicity.
*/
- if (fields[1] == 0 && fields[3] == 0) {
+ if (fields[1] == 0 && fields[3] == 0 &&
+ be->return_string_data != 1) {
/* No legal overrides, leave *argp unscathed */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -216,7 +217,7 @@ merge_grents(be, argp, fields)
g->gr_gid);
s += strlen(s);
if (fields[3] != 0) {
- strcpy(s, fields[3]);
+ (void) strcpy(s, fields[3]);
s += strlen(s);
} else {
char **memp;
@@ -235,10 +236,31 @@ merge_grents(be, argp, fields)
}
}
}
- parsestat = (*argp->str2ent)(buf, s - buf,
+
+ dlen = s - buf;
+
+ /*
+ * if asked, return the data in /etc file format
+ */
+ if (be->return_string_data == 1) {
+ /* reset the result ptr to the original value */
+ argp->buf.result = NULL;
+
+ if (dlen > argp->buf.buflen) {
+ parsestat = NSS_STR_PARSE_ERANGE;
+ } else {
+ (void) strncpy(argp->buf.buffer, buf, dlen);
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = dlen;
+ parsestat = NSS_SUCCESS;
+ }
+ } else {
+ parsestat = (*argp->str2ent)(buf, dlen,
argp->buf.result,
argp->buf.buffer,
argp->buf.buflen);
+ }
+
free(buf);
return (parsestat);
}
diff --git a/usr/src/lib/nsswitch/compat/common/getpwent.c b/usr/src/lib/nsswitch/compat/common/getpwent.c
index e31462443f..1219dab7fa 100644
--- a/usr/src/lib/nsswitch/compat/common/getpwent.c
+++ b/usr/src/lib/nsswitch/compat/common/getpwent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * getpwent.c
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * getpwent.c
*
* lib/nsswitch/compat/getpwent.c -- name-service-switch backend for getpwnam()
* et al that does 4.x compatibility. It looks in /etc/passwd; if it finds
@@ -60,7 +59,7 @@
static DEFINE_NSS_DB_ROOT(db_root);
-void
+static void
_nss_initf_passwd_compat(p)
nss_db_params_t *p;
{
@@ -92,7 +91,7 @@ getbyname(be, a)
compat_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_compat_XY_all(be, argp,
check_pwname, NSS_DBOP_PASSWD_BYNAME));
@@ -112,7 +111,7 @@ getbyuid(be, a)
compat_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_compat_XY_all(be, argp,
check_pwuid, NSS_DBOP_PASSWD_BYUID));
@@ -129,6 +128,8 @@ merge_pwents(be, argp, fields)
char *buf = malloc(NSS_LINELEN_PASSWD);
char *s;
int parsestat;
+ int len;
+ int buflen;
if (buf == 0) {
return (NSS_STR_PARSE_PARSE);
@@ -142,30 +143,60 @@ merge_pwents(be, argp, fields)
* That's what the SunOS 4.x code did; who are we to question it...
*/
s = buf;
- sprintf(s, "%s:", pw->pw_name);
- s += strlen(s);
- if (fields[1] != 0) {
- strcpy(s, fields[1]);
- } else {
- strcpy(s, pw->pw_passwd);
- if (pw->pw_age != 0) {
- s += strlen(s);
+ buflen = argp->buf.buflen;
+
+ if (fields[1] != 0)
+ len = snprintf(s, buflen, "%s:%s",
+ pw->pw_name, fields[1]);
+ else {
/* ====> Does this do the right thing? */
- sprintf(s, ",%s", pw->pw_age);
- }
+ if (pw->pw_age != 0 && *pw->pw_age != '\0')
+ len = snprintf(s, buflen, "%s:%s,%s",
+ pw->pw_name, pw->pw_passwd, pw->pw_age);
+ else
+ len = snprintf(s, buflen, "%s:%s",
+ pw->pw_name, pw->pw_passwd);
}
- s += strlen(s);
- sprintf(s, ":%d:%d:%s:%s:%s",
+
+ if (len > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+
+ s += len;
+ buflen -= len;
+ len = snprintf(s, buflen, ":%ld:%ld:%s:%s:%s",
pw->pw_uid,
pw->pw_gid,
fields[4] != 0 ? fields[4] : pw->pw_gecos,
fields[5] != 0 ? fields[5] : pw->pw_dir,
fields[6] != 0 ? fields[6] : pw->pw_shell);
- s += strlen(s);
- parsestat = (*argp->str2ent)(buf, s - buf,
+
+ if (len > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+
+ s += len;
+ len = s - buf;
+
+ /*
+ * if asked, return the data in /etc file format
+ */
+ if (be->return_string_data == 1) {
+ /* reset the result ptr to the original value */
+ argp->buf.result = NULL;
+
+ if (len > argp->buf.buflen) {
+ parsestat = NSS_STR_PARSE_ERANGE;
+ } else {
+ (void) strncpy(argp->buf.buffer, buf, len);
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = len;
+ parsestat = NSS_SUCCESS;
+ }
+ } else {
+ parsestat = (*argp->str2ent)(buf, len,
argp->buf.result,
argp->buf.buffer,
argp->buf.buflen);
+ }
free(buf);
return (parsestat);
}
diff --git a/usr/src/lib/nsswitch/compat/common/getspent.c b/usr/src/lib/nsswitch/compat/common/getspent.c
index c5671dcdef..96aba4f6e1 100644
--- a/usr/src/lib/nsswitch/compat/common/getspent.c
+++ b/usr/src/lib/nsswitch/compat/common/getspent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,12 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
* getspent.c
*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
* lib/nsswitch/compat/getspent.c -- name-service-switch backend for getspnam()
* It looks in /etc/shadow; if it finds shadow entries there that begin
* with "+" or "-", it consults other services. By default it uses NIS (YP),
@@ -55,7 +55,7 @@
static DEFINE_NSS_DB_ROOT(db_root);
-void
+static void
_nss_initf_shadow_compat(p)
nss_db_params_t *p;
{
@@ -87,7 +87,7 @@ getbyname(be, a)
compat_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_compat_XY_all(be, argp, check_spnamp,
NSS_DBOP_SHADOW_BYNAME));
@@ -116,10 +116,12 @@ merge_spents(be, argp, fields)
return (NSS_STR_PARSE_ERANGE);
}
if (sp->sp_namp != argp->buf.buffer) {
- memmove(argp->buf.buffer, sp->sp_namp, namelen);
+ (void) memmove(argp->buf.buffer,
+ sp->sp_namp, namelen);
sp->sp_namp = argp->buf.buffer;
}
- memcpy(argp->buf.buffer + namelen, fields[1], passlen);
+ (void) memcpy(argp->buf.buffer + namelen,
+ fields[1], passlen);
}
#define override(field, longp) \
@@ -142,7 +144,39 @@ merge_spents(be, argp, fields)
override(fields[6], &sp->sp_inact);
override(fields[7], &sp->sp_expire);
override(fields[8], &sp->sp_flag);
- return (NSS_STR_PARSE_SUCCESS);
+
+ /*
+ * if asked, return the data in /etc file format
+ */
+ if (be->return_string_data == 1) {
+ int n;
+ char b[16];
+
+ /* reset the result ptr to the original value */
+ argp->buf.result = NULL;
+
+#define printnum(num) sprintf(b, "%d", num)) ? b : ""
+
+ n = snprintf(argp->buf.buffer, argp->buf.buflen,
+ "%s:%s:%s:%s:%s:%s:%s:%s:%s", sp->sp_namp,
+ (sp->sp_pwdp ? sp->sp_pwdp : ""),
+ (sp->sp_lstchg >= 0 && printnum(sp->sp_lstchg),
+ (sp->sp_min >= 0 && printnum(sp->sp_min),
+ (sp->sp_max >= 0 && printnum(sp->sp_max),
+ (sp->sp_warn > 0 && printnum(sp->sp_warn),
+ (sp->sp_inact > 0 && printnum(sp->sp_inact),
+ (sp->sp_expire > 0 && printnum(sp->sp_expire),
+ (sp->sp_flag != 0 && printnum(sp->sp_flag));
+
+ if (n > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ else {
+ argp->returnlen = n - 1;
+ return (NSS_SUCCESS);
+ }
+
+ } else
+ return (NSS_STR_PARSE_SUCCESS);
}
static compat_backend_op_t shadow_ops[] = {
diff --git a/usr/src/lib/nsswitch/compat/common/getuserattr.c b/usr/src/lib/nsswitch/compat/common/getuserattr.c
index 00572fa644..653101eca1 100644
--- a/usr/src/lib/nsswitch/compat/common/getuserattr.c
+++ b/usr/src/lib/nsswitch/compat/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -34,7 +33,7 @@
static DEFINE_NSS_DB_ROOT(db_root);
-void
+static void
_nss_initf_userattr_compat(nss_db_params_t *p)
{
p->name = NSS_DBNAM_USERATTR;
@@ -91,6 +90,7 @@ static compat_backend_op_t userattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_compat_user_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/dns/Makefile.com b/usr/src/lib/nsswitch/dns/Makefile.com
index f4aa3f433c..23c89c32f8 100644
--- a/usr/src/lib/nsswitch/dns/Makefile.com
+++ b/usr/src/lib/nsswitch/dns/Makefile.com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -45,5 +44,7 @@ include ../../../Makefile.rootfs
# if no libresolv was provided by the application.
CPPFLAGS += -DNSS_DNS_LIBRESOLV=\"libresolv.so.2\"
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+
LDLIBS += -lnsl
DYNLIB1 = nss_dns.so$(VERS)
diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.c b/usr/src/lib/nsswitch/dns/common/dns_common.c
index da766c4d12..0ed02f1d23 100644
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,16 +19,27 @@
* CDDL HEADER END
*/
/*
- * dns_common.c
- *
- * Copyright (c) 1993,1998 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * dns_common.c
+ */
#include "dns_common.h"
+#pragma weak dn_expand
+#pragma weak res_ninit
+#pragma weak res_nsearch
+#pragma weak res_nclose
+#pragma weak ns_get16
+#pragma weak ns_get32
+#pragma weak __ns_get16
+#pragma weak __ns_get32
+
#define DNS_ALIASES 0
#define DNS_ADDRLIST 1
#define DNS_MAPDLIST 2
@@ -58,7 +68,8 @@ dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type)
if (*aliaspp <= (char *)&to_list[cnt+1])
return (NSS_STR_PARSE_ERANGE);
if (type == DNS_MAPDLIST) {
- struct in6_addr *addr6p = (struct in6_addr *) *aliaspp;
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
+ struct in6_addr *addr6p = (struct in6_addr *)*aliaspp;
(void) memset(addr6p, '\0', sizeof (struct in6_addr));
(void) memcpy(&addr6p->s6_addr[12], fstr,
@@ -96,7 +107,7 @@ ent2result(he, argp, af_type)
struct in6_addr *addrp6;
limit = argp->buf.buffer + buflen;
- host = (struct hostent *) argp->buf.result;
+ host = (struct hostent *)argp->buf.result;
buffer = argp->buf.buffer;
/* h_addrtype and h_length */
@@ -114,7 +125,7 @@ ent2result(he, argp, af_type)
/* h_addr_list */
if (af_type == AF_INET) {
- addrp = (struct in_addr *) ROUND_DOWN(limit, sizeof (*addrp));
+ addrp = (struct in_addr *)ROUND_DOWN(limit, sizeof (*addrp));
host->h_addr_list = (char **)
ROUND_UP(buffer, sizeof (char **));
ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list,
@@ -152,16 +163,368 @@ ent2result(he, argp, af_type)
return (ret);
}
+/*
+ * Convert the hostent structure into string in the following
+ * format:
+ *
+ * IP-address official-host-name nicknames ...
+ *
+ * If more than one IP-addresses matches the official-host-name,
+ * the above line will be followed by:
+ * IP-address-1 official-host-name
+ * IP-address-2 official-host-name
+ * ...
+ *
+ * This is so that the str2hostent function in libnsl
+ * can convert the string back to the original hostent
+ * data.
+ */
+int
+ent2str(
+ struct hostent *hp,
+ nss_XbyY_args_t *ap,
+ int af_type)
+{
+ char **p;
+ char obuf[INET6_ADDRSTRLEN];
+ void *addr;
+ struct in_addr in4;
+ int af;
+ int n;
+ const char *res;
+ char **q;
+ int l = ap->buf.buflen;
+ char *s = ap->buf.buffer;
+
+ /*
+ * for "hosts" lookup, we only want address type of
+ * AF_INET. For "ipnodes", we can have both AF_INET
+ * and AF_INET6.
+ */
+ if (af_type == AF_INET && hp->h_addrtype != AF_INET)
+ return (NSS_STR_PARSE_PARSE);
+
+ for (p = hp->h_addr_list; *p != 0; p++) {
+
+ if (p != hp->h_addr_list) {
+ *s = '\n';
+ s++;
+ l--;
+ }
+
+ if (hp->h_addrtype == AF_INET6) {
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)*p)) {
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
+ IN6_V4MAPPED_TO_INADDR((struct in6_addr *)*p,
+ &in4);
+ af = AF_INET;
+ addr = &in4;
+ } else {
+ af = AF_INET6;
+ addr = *p;
+ }
+ } else {
+ af = AF_INET;
+ addr = *p;
+ }
+ res = inet_ntop(af, addr, obuf, sizeof (obuf));
+ if (res == NULL)
+ return (NSS_STR_PARSE_PARSE);
+
+ if ((n = snprintf(s, l, "%s %s", res, hp->h_name)) >= l)
+ return (NSS_STR_PARSE_ERANGE);
+ l -= n;
+ s += n;
+ if (p == hp->h_addr_list) {
+ for (q = hp->h_aliases; q && *q; q++) {
+ if ((n = snprintf(s, l, " %s", *q)) >= l)
+ return (NSS_STR_PARSE_ERANGE);
+ l -= n;
+ s += n;
+ }
+ }
+ }
+
+ ap->returnlen = s - ap->buf.buffer;
+ return (NSS_STR_PARSE_SUCCESS);
+}
nss_backend_t *
_nss_dns_constr(dns_backend_op_t ops[], int n_ops)
{
dns_backend_ptr_t be;
- if ((be = (dns_backend_ptr_t) malloc(sizeof (*be))) == 0)
+ if ((be = (dns_backend_ptr_t)malloc(sizeof (*be))) == 0)
return (0);
be->ops = ops;
be->n_ops = n_ops;
- return ((nss_backend_t *) be);
+ return ((nss_backend_t *)be);
+}
+
+
+/*
+ * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
+ * nss2 get hosts/ipnodes with ttl backend DNS search engine.
+ *
+ * This API is given a pointer to a packed buffer, and the buffer size
+ * It's job is to perform the appropriate res_nsearch, extract the
+ * results and build a unmarshalled hosts/ipnodes result buffer.
+ * Additionally in the extended results a nssuint_t ttl is placed.
+ * This ttl is the lessor of the ttl's extracted from the result.
+ *
+ * ***Currently the first version of this API only performs simple
+ * single res_nsearch lookups for with T_A or T_AAAA results.
+ * Other searches are deferred to the generic API w/t ttls.
+ *
+ * This function is not a generic res_* operation. It only performs
+ * a single T_A or T_AAAA lookups***
+ *
+ * RETURNS: NSS_SUCCESS or NSS_ERROR
+ * If an NSS_ERROR result is returned, nscd is expected
+ * to resubmit the gethosts request using the old style
+ * nsswitch lookup format.
+ */
+
+struct tsd_priv {
+ struct __res_state *statp; /* dns state block */
+ union msg {
+ uchar_t buf[NS_MAXMSG]; /* max legal DNS answer size */
+ HEADER h;
+ } resbuf;
+ char aliases[NS_MAXMSG]; /* set of aliases */
+};
+
+static void ghttlcleanup(void *ptr)
+{
+ struct tsd_priv *priv = (struct tsd_priv *)ptr;
+
+ if (priv) {
+ if (priv->statp != NULL) {
+ res_nclose(priv->statp);
+ free((void *)priv->statp);
+ }
+ free(ptr);
+ }
+}
+
+nss_status_t
+_nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
+{
+ /* nss buffer variables */
+ nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
+ nss_XbyY_args_t arg;
+ char *dbname;
+ int dbop;
+ nss_status_t sret;
+ size_t bsize, blen;
+ char *bptr;
+ /* resolver query variables */
+ static mutex_t keylock;
+ static thread_key_t key;
+ static int once_per_keyname = 0;
+ struct tsd_priv *tsd = NULL;
+ const char *name;
+ int qtype;
+ /* answer parsing variables */
+ HEADER *hp;
+ uchar_t *cp; /* current location in message */
+ uchar_t *bom; /* start of message */
+ uchar_t *eom; /* end of message */
+ uchar_t *eor; /* end of record */
+ int ancount, qdcount;
+ int type, class;
+ nssuint_t nttl, ttl, *pttl; /* The purpose of this API */
+ int n, ret;
+ const char *np;
+ /* temporary buffers */
+ char nbuf[INET6_ADDRSTRLEN]; /* address parser */
+ char host[MAXHOSTNAMELEN]; /* result host name */
+ char ans[MAXHOSTNAMELEN]; /* record name */
+ char aname[MAXHOSTNAMELEN]; /* alias result (C_NAME) */
+ /* misc variables */
+ int af;
+ char *ap, *apc;
+ int hlen, alen, iplen, len;
+
+ if (!once_per_keyname) {
+ (void) mutex_lock(&keylock);
+ if (!once_per_keyname) {
+ (void) thr_keycreate(&key, ghttlcleanup);
+ once_per_keyname++;
+ }
+ (void) mutex_unlock(&keylock);
+ }
+ (void) thr_getspecific(key, (void **)&tsd);
+ if (tsd == NULL) {
+ tsd = (struct tsd_priv *)calloc(1, sizeof (struct tsd_priv));
+ (void) thr_setspecific(key, (void *)tsd);
+ (void) thr_getspecific(key, (void **)&tsd);
+ tsd->statp = (struct __res_state *)
+ calloc(1, sizeof (struct __res_state));
+ if (tsd->statp == NULL)
+ return (NSS_ERROR);
+ if (res_ninit(tsd->statp) == -1) {
+ free(tsd->statp);
+ return (NSS_ERROR);
+ }
+ }
+ ap = apc = (char *)tsd->aliases;
+ alen = 0;
+ ttl = (nssuint_t)0xFFFFFFF; /* start w/max, find smaller */
+
+ /* save space for ttl otherwise, why bother... */
+ bsize = pbuf->data_len - sizeof (nssuint_t);
+ bptr = (char *)buffer + pbuf->data_off;
+ blen = 0;
+ sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg);
+ if (sret != NSS_SUCCESS) {
+ return (NSS_ERROR);
+ }
+
+ if (ipnode) {
+ /* initially only handle the simple cases */
+ if (arg.key.ipnode.flags != 0)
+ return (NSS_ERROR);
+ name = arg.key.ipnode.name;
+ if (arg.key.ipnode.af_family == AF_INET6)
+ qtype = T_AAAA;
+ else
+ qtype = T_A;
+ } else {
+ name = arg.key.name;
+ qtype = T_A;
+ }
+ ret = res_nsearch(tsd->statp, name, C_IN, qtype,
+ tsd->resbuf.buf, NS_MAXMSG);
+ if (ret == -1) {
+ if (tsd->statp->res_h_errno == HOST_NOT_FOUND) {
+ pbuf->p_herrno = HOST_NOT_FOUND;
+ pbuf->p_status = NSS_NOTFOUND;
+ pbuf->data_len = 0;
+ return (NSS_NOTFOUND);
+ }
+ /* else lookup error - handle in general code */
+ return (NSS_ERROR);
+ }
+
+ cp = tsd->resbuf.buf;
+ hp = (HEADER *)&tsd->resbuf.h;
+ bom = cp;
+ eom = cp + ret;
+
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ cp += HFIXEDSZ;
+ if (qdcount != 1)
+ return (NSS_ERROR);
+ n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN);
+ if (n < 0) {
+ return (NSS_ERROR);
+ } else
+ hlen = strlen(host);
+ cp += n + QFIXEDSZ;
+ if (cp > eom)
+ return (NSS_ERROR);
+ while (ancount-- > 0 && cp < eom && blen < bsize) {
+ n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN);
+ if (n > 0) {
+ if (strncasecmp(host, ans, hlen) != 0)
+ return (NSS_ERROR); /* spoof? */
+ }
+ cp += n;
+ /* bounds check */
+ type = ns_get16(cp); /* type */
+ cp += INT16SZ;
+ class = ns_get16(cp); /* class */
+ cp += INT16SZ;
+ nttl = (nssuint_t)ns_get32(cp); /* ttl in sec */
+ if (nttl < ttl)
+ ttl = nttl;
+ cp += INT32SZ;
+ n = ns_get16(cp); /* len */
+ cp += INT16SZ;
+ if (class != C_IN) {
+ cp += n;
+ continue;
+ }
+ eor = cp + n;
+ if (type == T_CNAME) {
+ /* add an alias to the alias list */
+ n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN);
+ if (n > 0) {
+ len = strlen(aname);
+ if (len > 0) {
+ /*
+ * Just error out if there is an
+ * attempted buffer overflow exploit
+ * generic code will do a syslog
+ */
+ if (alen + len + 2 > NS_MAXMSG)
+ return (NSS_ERROR);
+ *apc++ = ' ';
+ alen++;
+ (void) strlcpy(apc, aname, len + 1);
+ alen += len;
+ apc += len;
+ }
+ }
+ cp += n;
+ continue;
+ }
+ if (type != qtype) {
+ cp += n;
+ continue;
+ }
+ /* check data size */
+ if ((type == T_A && n != INADDRSZ) ||
+ (type == T_AAAA && n != IN6ADDRSZ)) {
+ cp += n;
+ continue;
+ }
+ af = (type == T_A ? AF_INET : AF_INET6);
+ np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN);
+ if (np == NULL)
+ return (NSS_ERROR);
+ cp += n;
+ /* append IP host aliases to results */
+ iplen = strlen(np);
+ /* ip <SP> hostname [<SP>][aliases] */
+ len = iplen + 2 + hlen + alen;
+ if (alen > 0)
+ len++;
+ if (blen + len > bsize)
+ return (NSS_ERROR);
+ (void) strlcpy(bptr, np, bsize - blen);
+ blen += iplen;
+ bptr += iplen;
+ *bptr++ = ' ';
+ blen++;
+ (void) strlcpy(bptr, host, bsize - blen);
+ blen += hlen;
+ bptr += hlen;
+ if (alen > 0) {
+ *bptr++ = ' ';
+ blen++;
+ (void) strlcpy(bptr, ap, bsize - blen);
+ blen += alen;
+ bptr += alen;
+ }
+ *bptr++ = '\n';
+ blen++;
+ }
+ /* Presumably the buffer is now filled. */
+ len = ROUND_UP(blen, sizeof (nssuint_t));
+ /* still room? */
+ if (len + sizeof (nssuint_t) > pbuf->data_len) {
+ /* sigh, no, what happened? */
+ return (NSS_ERROR);
+ }
+ pbuf->ext_off = pbuf->data_off + len;
+ pbuf->ext_len = sizeof (nssuint_t);
+ pbuf->data_len = blen;
+ pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off));
+ *pttl = ttl;
+ return (NSS_SUCCESS);
}
diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.h b/usr/src/lib/nsswitch/dns/common/dns_common.h
index 7861cbb683..f60a37e436 100644
--- a/usr/src/lib/nsswitch/dns/common/dns_common.h
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1993, 1998-1999 by Sun Microsystems, Inc.
- * All rights reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
* Common code and structures used by name-service-switch "dns" backends.
*/
@@ -39,10 +39,12 @@
#include <netdb.h>
#include <strings.h>
#include <thread.h>
+#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <syslog.h>
#include <nsswitch.h>
+#include <nss_common.h>
#include <nss_dbdefs.h>
#include <stdlib.h>
#include <signal.h>
@@ -74,13 +76,17 @@ extern mutex_t one_lane;
extern int _thr_sigsetmask(int, const sigset_t *, sigset_t *);
extern int _mutex_lock(mutex_t *);
extern int _mutex_unlock(mutex_t *);
-extern const char *inet_ntop(int, const void *, char *, size_t);
extern int ent2result(struct hostent *, nss_XbyY_args_t *, int);
+extern int ent2str(struct hostent *, nss_XbyY_args_t *, int);
nss_backend_t *_nss_dns_constr(dns_backend_op_t *, int);
extern nss_status_t _herrno2nss(int);
+nss_status_t _nss_dns_gethost_withttl(void *buf, size_t bufsize, int ipnode);
+nss_status_t _nss_get_dns_hosts_name(dns_backend_ptr_t *, void **, size_t *);
+nss_status_t _nss_get_dns_ipnodes_name(dns_backend_ptr_t *, void **, size_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/nsswitch/dns/common/dns_mt.c b/usr/src/lib/nsswitch/dns/common/dns_mt.c
index 7e236c40eb..bf6ac565c4 100644
--- a/usr/src/lib/nsswitch/dns/common/dns_mt.c
+++ b/usr/src/lib/nsswitch/dns/common/dns_mt.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1993, 1998-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -109,11 +108,10 @@ mutex_t one_lane = DEFAULTMUTEX;
void
_nss_dns_init(void)
{
- struct hostent *(*f_hostent_ptr)();
void *reslib, (*f_void_ptr)();
/* If no libresolv library, then load one */
- if ((f_hostent_ptr = res_gethostbyname) == 0) {
+ if (res_gethostbyname == 0) {
if ((reslib =
dlopen(NSS_DNS_LIBRESOLV, RTLD_LAZY|RTLD_GLOBAL)) != 0) {
/* Turn off /etc/hosts fall back in libresolv */
diff --git a/usr/src/lib/nsswitch/dns/common/gethostent.c b/usr/src/lib/nsswitch/dns/common/gethostent.c
index 38c8a44a3a..af365f4f2a 100644
--- a/usr/src/lib/nsswitch/dns/common/gethostent.c
+++ b/usr/src/lib/nsswitch/dns/common/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1993, 1998-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -144,10 +143,22 @@ getbyname(be, a)
he = _gethostbyname(&argp->h_errno, argp->key.name);
if (he != NULL) {
- ret = ent2result(he, a, AF_INET);
- if (ret == NSS_STR_PARSE_SUCCESS) {
- argp->returnval = argp->buf.result;
+ if (argp->buf.result == NULL) {
+ /*
+ * if asked to return data in string,
+ * convert the hostent structure into
+ * string data
+ */
+ ret = ent2str(he, a, AF_INET);
+ if (ret == NSS_STR_PARSE_SUCCESS)
+ argp->returnval = argp->buf.buffer;
} else {
+ ret = ent2result(he, a, AF_INET);
+ if (ret == NSS_STR_PARSE_SUCCESS)
+ argp->returnval = argp->buf.result;
+ }
+
+ if (ret != NSS_STR_PARSE_SUCCESS) {
argp->h_errno = HOST_NOT_FOUND;
if (ret == NSS_STR_PARSE_ERANGE) {
argp->erange = 1;
@@ -176,6 +187,7 @@ getbyaddr(be, a)
* Exposing a DNS backend specific interface so that it doesn't conflict
* with other getbyaddr() routines from other switch backends.
*/
+/*ARGSUSED*/
nss_status_t
__nss_dns_getbyaddr(be, a)
dns_backend_ptr_t be;
@@ -195,11 +207,12 @@ __nss_dns_getbyaddr(be, a)
switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)argp->key.hostaddr.addr)) {
addrp = &unmapv4;
addrlen = sizeof (unmapv4);
af = AF_INET;
- memcpy(addrp, &argp->key.hostaddr.addr[12], addrlen);
+ (void) memcpy(addrp, &argp->key.hostaddr.addr[12], addrlen);
} else {
addrp = (void *)argp->key.hostaddr.addr;
addrlen = argp->key.hostaddr.len;
@@ -217,7 +230,18 @@ __nss_dns_getbyaddr(be, a)
if (n < MAXHOSTNAMELEN-1 && hbuf[n-1] != '.') {
(void) strcat(hbuf, ".");
}
- ret = ent2result(he, a, argp->key.hostaddr.type);
+
+ /*
+ * if asked to return data in string,
+ * convert the hostent structure into
+ * string data
+ */
+ if (argp->buf.result == NULL)
+ ret = ent2str(he, a, argp->key.hostaddr.type);
+ else
+ ret = ent2result(he, a,
+ argp->key.hostaddr.type);
+
save_h_errno = argp->h_errno;
}
if (ret == NSS_STR_PARSE_SUCCESS) {
@@ -242,7 +266,12 @@ __nss_dns_getbyaddr(be, a)
if (memcmp(*ans, addrp, addrlen) ==
0) {
argp->h_errno = save_h_errno;
- argp->returnval = argp->buf.result;
+ if (argp->buf.result == NULL)
+ argp->returnval =
+ argp->buf.buffer;
+ else
+ argp->returnval =
+ argp->buf.result;
break;
}
} else {
@@ -259,12 +288,16 @@ __nss_dns_getbyaddr(be, a)
* this go. And return the name from byaddr.
*/
argp->h_errno = save_h_errno;
- argp->returnval = argp->buf.result;
+ if (argp->buf.result == NULL)
+ argp->returnval = argp->buf.buffer;
+ else
+ argp->returnval = argp->buf.result;
}
/* we've been spoofed, make sure to log it. */
if (argp->h_errno == HOST_NOT_FOUND) {
if (argp->key.hostaddr.type == AF_INET)
syslog(LOG_NOTICE, "gethostbyaddr: %s != %s",
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
hbuf, inet_ntoa(*(struct in_addr *)argp->key.hostaddr.addr));
else
syslog(LOG_NOTICE, "gethostbyaddr: %s != %s",
@@ -414,3 +447,22 @@ _nss_dns_hosts_constr(dummy1, dummy2, dummy3)
return (_nss_dns_constr(host_ops,
sizeof (host_ops) / sizeof (host_ops[0])));
}
+
+/*
+ * optional NSS2 packed backend gethostsbyname with ttl
+ * entry point.
+ *
+ * Returns:
+ * NSS_SUCCESS - successful
+ * NSS_NOTFOUND - successful but nothing found
+ * NSS_ERROR - fallback to NSS backend lookup mode
+ * If successful, buffer will be filled with valid data
+ *
+ */
+
+/*ARGSUSED*/
+nss_status_t
+_nss_get_dns_hosts_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep)
+{
+ return (_nss_dns_gethost_withttl(*bufp, *sizep, 0));
+}
diff --git a/usr/src/lib/nsswitch/dns/common/gethostent6.c b/usr/src/lib/nsswitch/dns/common/gethostent6.c
index e92ce6a356..b2d71d6b24 100644
--- a/usr/src/lib/nsswitch/dns/common/gethostent6.c
+++ b/usr/src/lib/nsswitch/dns/common/gethostent6.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 1993-2000, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- *
+ */
+/*
* gethostent6.c
*/
@@ -115,7 +115,7 @@ cloneName(struct hostent *h, int *outerr) {
return (0);
}
- memcpy(name, h->h_name, len+1);
+ (void) memcpy(name, h->h_name, len+1);
*errp = 0;
return (name);
@@ -130,7 +130,7 @@ cloneName(struct hostent *h, int *outerr) {
* Note: The pointers to the addresses in the moreAddrs[] array are copied,
* but not the IP addresses themselves.
*/
-struct in6_addr **
+static struct in6_addr **
cloneAddrList(struct hostent *h, struct in6_addr **moreAddrs, int *outerr) {
struct in6_addr **addrArray, *addrList;
@@ -176,10 +176,12 @@ cloneAddrList(struct hostent *h, struct in6_addr **moreAddrs, int *outerr) {
for (i = 0; i < addrCount; i++) {
addrArray[i] = addrList;
if (domap) {
+ /* LINTED: E_BAD_PTR_CAST_ALIGN */
IN6_INADDR_TO_V4MAPPED(
(struct in_addr *)h->h_addr_list[i], addrArray[i]);
} else {
- memcpy(addrArray[i], h->h_addr_list[i], addrlen);
+ (void) memcpy(addrArray[i], h->h_addr_list[i],
+ addrlen);
}
addrList = PTROFF(addrList, addrlen);
}
@@ -211,7 +213,7 @@ static char **
cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
char **aliasArray, *aliasList;
- int i, j, k, aliasCount, mergeAliasCount = 0, realMac = 0;
+ int i, j, aliasCount, mergeAliasCount = 0, realMac = 0;
int stringSize = 0;
int error, *errp;
@@ -259,7 +261,7 @@ cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
for (i = 0; i < aliasCount; i++) {
int len = strlen(h->h_aliases[i]);
aliasArray[i] = aliasList;
- memcpy(aliasArray[i], h->h_aliases[i], len+1);
+ (void) memcpy(aliasArray[i], h->h_aliases[i], len+1);
aliasList = PTROFF(aliasList, RNDUP(len+1));
}
@@ -275,7 +277,7 @@ cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
return (aliasArray);
}
-
+/*ARGSUSED*/
static nss_status_t
getbyname(be, a)
dns_backend_ptr_t be;
@@ -407,11 +409,23 @@ getbyname(be, a)
argp->h_errno = v6_h_errno;
}
- if (he != 0) {
- ret = ent2result(he, a, AF_INET6);
- if (ret == NSS_STR_PARSE_SUCCESS) {
- argp->returnval = argp->buf.result;
+ if (he != NULL) {
+ /*
+ * if asked to return data in string,
+ * convert the hostent structure into
+ * string data
+ */
+ if (argp->buf.result == NULL) {
+ ret = ent2str(he, a, AF_INET6);
+ if (ret == NSS_STR_PARSE_SUCCESS)
+ argp->returnval = argp->buf.buffer;
} else {
+ ret = ent2result(he, a, AF_INET6);
+ if (ret == NSS_STR_PARSE_SUCCESS)
+ argp->returnval = argp->buf.result;
+ }
+
+ if (ret != NSS_STR_PARSE_SUCCESS) {
argp->h_errno = HOST_NOT_FOUND;
if (ret == NSS_STR_PARSE_ERANGE) {
argp->erange = 1;
@@ -532,3 +546,22 @@ _nss_dns_ipnodes_constr(dummy1, dummy2, dummy3)
return (_nss_dns_constr(ipnodes_ops,
sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
}
+
+/*
+ * optional NSS2 packed backend gethostsbyipnode with ttl
+ * entry point.
+ *
+ * Returns:
+ * NSS_SUCCESS - successful
+ * NSS_NOTFOUND - successful but nothing found
+ * NSS_ERROR - fallback to NSS backend lookup mode
+ * If successful, buffer will be filled with valid data
+ *
+ */
+
+/*ARGSUSED*/
+nss_status_t
+_nss_get_dns_ipnodes_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep)
+{
+ return (_nss_dns_gethost_withttl(*bufp, *sizep, 1));
+}
diff --git a/usr/src/lib/nsswitch/dns/common/mapfile-vers b/usr/src/lib/nsswitch/dns/common/mapfile-vers
index 6e44ffe568..9aa3d5ff1a 100644
--- a/usr/src/lib/nsswitch/dns/common/mapfile-vers
+++ b/usr/src/lib/nsswitch/dns/common/mapfile-vers
@@ -1,15 +1,14 @@
#
#ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -41,6 +40,8 @@ SUNWprivate_1.1 {
global:
_nss_dns_hosts_constr;
_nss_dns_ipnodes_constr;
+ _nss_get_dns_hosts_name;
+ _nss_get_dns_ipnodes_name;
local:
*;
};
diff --git a/usr/src/lib/nsswitch/files/Makefile.com b/usr/src/lib/nsswitch/files/Makefile.com
index f6105144d7..0f5ff82629 100644
--- a/usr/src/lib/nsswitch/files/Makefile.com
+++ b/usr/src/lib/nsswitch/files/Makefile.com
@@ -61,8 +61,10 @@ include ../../Makefile.com
include ../../../Makefile.rootfs
CPPFLAGS += -I../../../common/inc
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+LINTFLAGS64 += -erroff=E_GLOBAL_COULD_BE_STATIC2
-LDLIBS += -lnsl
+LDLIBS += -lsocket -lnsl
DYNLIB1 = nss_files.so$(VERS)
all: $(DYNLIB1) fnamecheck
diff --git a/usr/src/lib/nsswitch/files/common/bootparams_getbyname.c b/usr/src/lib/nsswitch/files/common/bootparams_getbyname.c
index ef51910acb..e1e88b1ced 100644
--- a/usr/src/lib/nsswitch/files/common/bootparams_getbyname.c
+++ b/usr/src/lib/nsswitch/files/common/bootparams_getbyname.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,11 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
* files/bootparams_getbyname.c -- "files" backend for
* nsswitch "bootparams" database.
- *
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -44,7 +43,7 @@ getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
nss_status_t res;
/* bootparams_getbyname() has not set/endent; rewind on each call */
@@ -108,14 +107,14 @@ _nss_files_XY_bootparams(be, args, filter)
* _nss_files_read_line does process the '\' that are used
* in /etc/bootparams for continuation and gives one long
* buffer.
- *
+ *
* linelen counts the characters up to but excluding the '\n'
*/
if ((linelen = _nss_files_read_line(be->f, instr,
be->minbuf)) < 0) {
/* End of file */
args->returnval = 0;
- args->erange = 0;
+ args->returnlen = 0;
break;
}
@@ -158,6 +157,7 @@ _nss_files_XY_bootparams(be, args, filter)
(void) memcpy(args->buf.buffer, p, linelen);
args->buf.buffer[linelen] = '\0';
args->returnval = args->buf.result;
+ args->returnlen = linelen;
res = NSS_SUCCESS;
break;
}
diff --git a/usr/src/lib/nsswitch/files/common/ether_addr.c b/usr/src/lib/nsswitch/files/common/ether_addr.c
index 4731e0c354..b8900cf043 100644
--- a/usr/src/lib/nsswitch/files/common/ether_addr.c
+++ b/usr/src/lib/nsswitch/files/common/ether_addr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,9 @@
* CDDL HEADER END
*/
/*
- * files/ether_addr.c -- "files" backend for nsswitch "ethers" database
+ * files/ether_addr.c -- "files" backend for nsswitch "ethers" database
*
- * Copyright 1988-1995,2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,14 +43,38 @@
#include <nss_dbdefs.h>
#include "files_common.h"
#include <strings.h>
+#include <ctype.h>
#define _PATH_ETHERS "/etc/ethers"
+#define DIGIT(x) \
+ (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
static int
-check_host(args)
- nss_XbyY_args_t *args;
+check_host(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- return (strcmp(args->buf.buffer, args->key.name) == 0);
+ const char *limit, *linep, *keyp;
+ linep = line;
+ limit = line + linelen;
+
+ /* skip leading spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* skip mac address */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ if (linep == limit)
+ return (0);
+
+ /* compare the host name */
+ keyp = argp->key.name;
+ while (*keyp != '\0' && linep < limit && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (*keyp == '\0' && linep == limit);
}
static nss_status_t
@@ -63,21 +86,57 @@ getbyhost(be, a)
char hostname[MAXHOSTNAMELEN];
nss_status_t res;
- argp->buf.buffer = hostname;
- argp->buf.buflen = MAXHOSTNAMELEN;
+ /*
+ * use the buffer passed in if result is to be returned
+ * in /etc file format
+ */
+ if (argp->buf.result != NULL) {
+ argp->buf.buffer = hostname;
+ argp->buf.buflen = MAXHOSTNAMELEN;
+ }
res = _nss_files_XY_all(be, argp, 0, argp->key.name, check_host);
- argp->buf.buffer = NULL;
- argp->buf.buflen = 0;
+ if (argp->buf.result != NULL) {
+ argp->buf.buffer = NULL;
+ argp->buf.buflen = 0;
+ }
+
return (res);
}
static int
-check_ether(args)
- nss_XbyY_args_t *args;
+check_ether(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- return (ether_cmp(args->buf.result, args->key.ether) == 0);
+
+ const char *limit, *linep;
+ uchar_t ether[6];
+ ptrdiff_t i;
+ int n;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* skip leading spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ for (i = 0; i < 6; i++) {
+ n = 0;
+ while (linep < limit && isxdigit(*linep)) {
+ n = 16 * n + DIGIT(*linep);
+ linep++;
+ }
+ if (*linep != ':' && i < 5) {
+ return (0);
+ } else if (*linep == ':' && i == 5) {
+ return (0);
+ } else {
+ linep++;
+ ether[i] = (uchar_t)n;
+ }
+ }
+ return (ether_cmp((void *)ether, (void *)argp->key.ether) == 0);
}
static nss_status_t
diff --git a/usr/src/lib/nsswitch/files/common/files_common.c b/usr/src/lib/nsswitch/files/common/files_common.c
index bdf03a3ca9..0f89f25d0b 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.c
+++ b/usr/src/lib/nsswitch/files/common/files_common.c
@@ -41,6 +41,7 @@
#include <poll.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <sys/mman.h>
/*ARGSUSED*/
nss_status_t
@@ -69,7 +70,7 @@ _nss_files_endent(be, dummy)
void *dummy;
{
if (be->f != 0) {
- fclose(be->f);
+ (void) fclose(be->f);
be->f = 0;
}
if (be->buf != 0) {
@@ -186,7 +187,7 @@ _nss_files_do_all(be, args, filter, func)
} while (res == NSS_NOTFOUND);
- _nss_files_endent(be, 0);
+ (void) _nss_files_endent(be, 0);
return (res);
}
@@ -208,6 +209,8 @@ _nss_files_XY_all(be, args, netdb, filter, check)
int parsestat;
int (*func)();
+ if (filter != NULL && *filter == '\0')
+ return (NSS_NOTFOUND);
if (be->buf == 0 &&
(be->buf = malloc(be->minbuf)) == 0) {
return (NSS_UNAVAIL); /* really panic, malloc failed */
@@ -230,7 +233,7 @@ _nss_files_XY_all(be, args, netdb, filter, check)
be->minbuf)) < 0) {
/* End of file */
args->returnval = 0;
- args->erange = 0;
+ args->returnlen = 0;
break;
}
if (filter != 0 && strstr(instr, filter) == 0) {
@@ -277,17 +280,21 @@ _nss_files_XY_all(be, args, netdb, filter, check)
}
args->returnval = 0;
+ args->returnlen = 0;
+
+ if (check != NULL && (*check)(args, instr, linelen) == 0)
+ continue;
func = args->str2ent;
parsestat = (*func)(instr, linelen, args->buf.result,
args->buf.buffer, args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
- args->returnval = args->buf.result;
- if (check == 0 || (*check)(args)) {
- res = NSS_SUCCESS;
- break;
- }
+ args->returnval = (args->buf.result != NULL)?
+ args->buf.result : args->buf.buffer;
+ args->returnlen = linelen;
+ res = NSS_SUCCESS;
+ break;
} else if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
break;
@@ -339,15 +346,22 @@ _nss_files_hash_destroy(files_hash_t *fhp)
extern void __nss_use_files_hash(void);
#endif /* pic */
+/*ARGSUSED*/
nss_status_t
_nss_files_XY_hash(files_backend_ptr_t be, nss_XbyY_args_t *args,
int netdb, files_hash_t *fhp, int hashop, files_XY_check_func check)
{
+ /* LINTED E_FUNC_VAR_UNUSED */
int fd, retries, ht;
+ /* LINTED E_FUNC_VAR_UNUSED */
uint_t hash, line, f;
+ /* LINTED E_FUNC_VAR_UNUSED */
files_hashent_t *hp, *htab;
+ /* LINTED E_FUNC_VAR_UNUSED */
char *cp, *first, *last;
+ /* LINTED E_FUNC_VAR_UNUSED */
nss_XbyY_args_t xargs;
+ /* LINTED E_FUNC_VAR_UNUSED */
struct stat64 st;
#ifndef PIC
@@ -375,26 +389,30 @@ retry:
st.st_mtim.tv_nsec == fhp->fh_mtime.tv_nsec &&
fhp->fh_table != NULL) {
htab = &fhp->fh_table[hashop * fhp->fh_size];
- hash = fhp->fh_hash_func[hashop](args, 1);
+ hash = fhp->fh_hash_func[hashop](args, 1, NULL, 0);
for (hp = htab[hash % fhp->fh_size].h_first; hp != NULL;
hp = hp->h_next) {
if (hp->h_hash != hash)
continue;
line = hp - htab;
+ if ((*check)(args, fhp->fh_line[line].l_start,
+ fhp->fh_line[line].l_len) == 0)
+ continue;
if ((*args->str2ent)(fhp->fh_line[line].l_start,
fhp->fh_line[line].l_len, args->buf.result,
args->buf.buffer, args->buf.buflen) ==
NSS_STR_PARSE_SUCCESS) {
- args->returnval = args->buf.result;
- if ((*check)(args)) {
- mutex_unlock(&fhp->fh_lock);
- return (NSS_SUCCESS);
- }
+ args->returnval = (args->buf.result)?
+ args->buf.result:args->buf.buffer;
+ args->returnlen = fhp->fh_line[line].l_len;
+ mutex_unlock(&fhp->fh_lock);
+ return (NSS_SUCCESS);
} else {
args->erange = 1;
}
}
args->returnval = 0;
+ args->returnlen = 0;
mutex_unlock(&fhp->fh_lock);
return (NSS_NOTFOUND);
}
@@ -461,14 +479,6 @@ retry:
if (fhp->fh_line == NULL || fhp->fh_table == NULL)
goto unavail;
- xargs = *args;
- xargs.buf.result = malloc(fhp->fh_resultsize + fhp->fh_bufsize);
- if (xargs.buf.result == NULL)
- goto unavail;
- xargs.buf.buffer = (char *)xargs.buf.result + fhp->fh_resultsize;
- xargs.buf.buflen = fhp->fh_bufsize;
- xargs.returnval = xargs.buf.result;
-
line = 0;
cp = fhp->fh_file_start;
while (cp < fhp->fh_file_end) {
@@ -494,18 +504,14 @@ retry:
--last;
*++last = '\0';
}
- if ((*xargs.str2ent)(first, last - first,
- xargs.buf.result, xargs.buf.buffer, xargs.buf.buflen) !=
- NSS_STR_PARSE_SUCCESS)
- continue;
for (ht = 0; ht < fhp->fh_nhtab; ht++) {
hp = &fhp->fh_table[ht * fhp->fh_size + line];
- hp->h_hash = fhp->fh_hash_func[ht](&xargs, 0);
+ hp->h_hash = fhp->fh_hash_func[ht](&xargs, 0, first,
+ last - first);
}
fhp->fh_line[line].l_start = first;
fhp->fh_line[line++].l_len = last - first;
}
- free(xargs.buf.result);
/*
* Populate the hash tables in reverse order so that the hash chains
@@ -561,13 +567,13 @@ _nss_files_destr(be, dummy)
{
if (be != 0) {
if (be->f != 0) {
- _nss_files_endent(be, 0);
+ (void) _nss_files_endent(be, 0);
}
if (be->hashinfo != NULL) {
- mutex_lock(&be->hashinfo->fh_lock);
+ (void) mutex_lock(&be->hashinfo->fh_lock);
if (--be->hashinfo->fh_refcnt == 0)
_nss_files_hash_destroy(be->hashinfo);
- mutex_unlock(&be->hashinfo->fh_lock);
+ (void) mutex_unlock(&be->hashinfo->fh_lock);
}
free(be);
}
@@ -596,10 +602,80 @@ _nss_files_constr(ops, n_ops, filename, min_bufsize, fhp)
be->hashinfo = fhp;
if (fhp != NULL) {
- mutex_lock(&fhp->fh_lock);
+ (void) mutex_lock(&fhp->fh_lock);
fhp->fh_refcnt++;
- mutex_unlock(&fhp->fh_lock);
+ (void) mutex_unlock(&fhp->fh_lock);
}
return ((nss_backend_t *)be);
}
+
+int
+_nss_files_check_name_colon(nss_XbyY_args_t *argp, const char *line,
+ int linelen)
+{
+ const char *linep, *limit;
+ const char *keyp = argp->key.name;
+
+ linep = line;
+ limit = line + linelen;
+ while (*keyp && linep < limit && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (linep < limit && *keyp == '\0' && *linep == ':');
+}
+
+/*
+ * This routine is used to parse lines of the form:
+ * name number aliases
+ * It returns 1 if the key in argp matches any one of the
+ * names in the line, otherwise 0
+ * Used by rpc, networks, protocols
+ */
+int
+_nss_files_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
+ int linelen)
+{
+ const char *limit, *linep, *keyp;
+
+ linep = line;
+ limit = line + linelen;
+ keyp = argp->key.name;
+
+ /* compare name */
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && linep < limit && isspace(*linep))
+ return (1);
+ /* skip remainder of the name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* compare with the aliases */
+ while (linep < limit) {
+ /*
+ * 1st pass: skip number
+ * Other passes: skip remainder of the alias name, if any
+ */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* compare with the alias name */
+ keyp = argp->key.name;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && (linep == limit || isspace(*linep)))
+ return (1);
+ }
+ return (0);
+}
diff --git a/usr/src/lib/nsswitch/files/common/files_common.h b/usr/src/lib/nsswitch/files/common/files_common.h
index 87980f8310..9f7457a033 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.h
+++ b/usr/src/lib/nsswitch/files/common/files_common.h
@@ -45,12 +45,12 @@ extern "C" {
typedef struct files_backend *files_backend_ptr_t;
typedef nss_status_t (*files_backend_op_t)(files_backend_ptr_t, void *);
-typedef u_int (*files_hash_func)(nss_XbyY_args_t *, int);
+typedef uint_t (*files_hash_func)(nss_XbyY_args_t *, int, const char *, int);
typedef struct files_hashent {
struct files_hashent *h_first;
struct files_hashent *h_next;
- u_int h_hash;
+ uint_t h_hash;
} files_hashent_t;
typedef struct {
@@ -92,7 +92,8 @@ struct files_backend {
* generic work for nss_XbyY_args_t backends (calls cstr2ent etc).
*/
typedef nss_status_t (*files_do_all_func_t)(const char *, int, void *args);
-typedef int (*files_XY_check_func)(nss_XbyY_args_t *);
+typedef int (*files_XY_check_func)(nss_XbyY_args_t *,
+ const char *, int);
#if defined(__STDC__)
extern nss_backend_t *_nss_files_constr(files_backend_op_t *ops,
@@ -133,6 +134,9 @@ extern nss_status_t _nss_files_XY_all();
extern nss_status_t _nss_files_XY_hash();
#endif
+int _nss_files_check_name_aliases(nss_XbyY_args_t *, const char *, int);
+int _nss_files_check_name_colon(nss_XbyY_args_t *, const char *, int);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/nsswitch/files/common/getauthattr.c b/usr/src/lib/nsswitch/files/common/getauthattr.c
index df236111ec..bf02ce214c 100644
--- a/usr/src/lib/nsswitch/files/common/getauthattr.c
+++ b/usr/src/lib/nsswitch/files/common/getauthattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -35,24 +34,14 @@
* files/getauthattr.c --
* "files" backend for nsswitch "auth_attr" database
*/
-static int
-check_name(nss_XbyY_args_t *args)
-{
- authstr_t *auth = (authstr_t *)args->returnval;
- const char *name = args->key.name;
-
- if (strcmp(auth->name, name) == 0) {
- return (1);
- }
- return (0);
-}
static nss_status_t
getbyname(files_backend_ptr_t be, void *a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_colon));
}
static files_backend_op_t authattr_ops[] = {
@@ -63,6 +52,7 @@ static files_backend_op_t authattr_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_auth_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/files/common/getauuser.c b/usr/src/lib/nsswitch/files/common/getauuser.c
index b47525e416..08a79e271f 100644
--- a/usr/src/lib/nsswitch/files/common/getauuser.c
+++ b/usr/src/lib/nsswitch/files/common/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -35,24 +34,14 @@
* files/getauuser.c --
* "files" backend for nsswitch "audit_user" database
*/
-static int
-check_name(nss_XbyY_args_t *args)
-{
- au_user_str_t *au_user = (au_user_str_t *)args->returnval;
- const char *name = args->key.name;
-
- if (strcmp(au_user->au_name, name) == 0) {
- return (1);
- }
- return (0);
-}
static nss_status_t
getbyname(files_backend_ptr_t be, void *a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_colon));
}
static files_backend_op_t auuser_ops[] = {
@@ -63,6 +52,7 @@ static files_backend_op_t auuser_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_audit_user_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
diff --git a/usr/src/lib/nsswitch/files/common/getexecattr.c b/usr/src/lib/nsswitch/files/common/getexecattr.c
index 502c0112b9..ac9e50ad3a 100644
--- a/usr/src/lib/nsswitch/files/common/getexecattr.c
+++ b/usr/src/lib/nsswitch/files/common/getexecattr.c
@@ -52,29 +52,47 @@ extern int _readbufline(char *, int, char *, int, int *);
extern char *_exec_wild_id(char *, const char *);
extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
-typedef int (*_exec_XY_check_func) (nss_XbyY_args_t *);
-
/*
* check_match: returns 1 if matching entry found, else returns 0.
*/
static int
-check_match(nss_XbyY_args_t *argp)
+check_match(nss_XbyY_args_t *argp, const char *line, int linelen)
{
+ const char *limit, *linep, *keyp;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
- const char *name = _priv_exec->name;
- const char *type = _priv_exec->type;
- const char *id = _priv_exec->id;
- const char *policy = _priv_exec->policy;
- execstr_t *exec = (execstr_t *)argp->returnval;
-
- if ((policy && exec->policy && (strcmp(policy, exec->policy) != 0)) ||
- (name && exec->name && (strcmp(name, exec->name) != 0)) ||
- (type && exec->type && (strcmp(type, exec->type) != 0)) ||
- (id && exec->id && (strcmp(id, exec->id) != 0))) {
- return (0);
+ const char *exec_field[6];
+ int i;
+
+ exec_field[0] = _priv_exec->name; /* name */
+ exec_field[1] = _priv_exec->policy; /* policy */
+ exec_field[2] = _priv_exec->type; /* type */
+ exec_field[3] = NULL; /* res1 */
+ exec_field[4] = NULL; /* res2 */
+ exec_field[5] = _priv_exec->id; /* id */
+ /* No need to check attr field */
+
+ linep = line;
+ limit = line + linelen;
+
+ for (i = 0; i < 6; i++) {
+ keyp = exec_field[i];
+ if (keyp) {
+ /* compare field */
+ while (*keyp && linep < limit &&
+ *linep != ':' && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp || linep == limit || *linep != ':')
+ return (0);
+ } else {
+ /* skip field */
+ while (linep < limit && *linep != ':')
+ linep++;
+ }
+ linep++;
}
-
return (1);
}
@@ -90,7 +108,6 @@ _exec_files_XY_all(files_backend_ptr_t be,
int f_size = 0;
time_t f_time = 0;
static time_t read_time = 0;
- char *key = NULL;
char *first;
char *last;
static char *f_buf = NULL;
@@ -169,16 +186,15 @@ _exec_files_XY_all(files_backend_ptr_t be,
}
res = NSS_NOTFOUND;
+ /*CONSTCOND*/
while (1) {
int linelen = 0;
- int check_stat = 0;
char *instr = be->buf;
linelen = _readbufline(f_buf, f_size, instr, be->minbuf,
&lastlen);
if (linelen < 0) {
/* End of file */
- argp->erange = 0;
break;
}
@@ -235,26 +251,25 @@ _exec_files_XY_all(files_backend_ptr_t be,
if (first != instr)
instr = first;
- /*
- * Parse the entry.
- */
+ /* Check the entry */
argp->returnval = NULL;
+ argp->returnlen = 0;
+ if (check_match(argp, instr, linelen) == 0)
+ continue;
+
+ /* Marshall the data */
parse_stat = (*argp->str2ent)(instr, linelen, argp->buf.result,
argp->buf.buffer, argp->buf.buflen);
if (parse_stat == NSS_STR_PARSE_SUCCESS) {
- argp->returnval = argp->buf.result;
- if (check_match(argp)) {
- res = NSS_SUCCESS;
- if (_priv_exec->search_flag == GET_ONE) {
- break;
- } else if (_doexeclist(argp) == 0) {
- res = NSS_UNAVAIL;
- break;
- }
- } else {
- argp->returnval = NULL;
- memset(argp->buf.buffer, NULL,
- argp->buf.buflen);
+ argp->returnval = (argp->buf.result != NULL)?
+ argp->buf.result : argp->buf.buffer;
+ argp->returnlen = linelen;
+ res = NSS_SUCCESS;
+ if (_priv_exec->search_flag == GET_ONE) {
+ break;
+ } else if (_doexeclist(argp) == 0) {
+ res = NSS_UNAVAIL;
+ break;
}
} else if (parse_stat == NSS_STR_PARSE_ERANGE) {
argp->erange = 1;
@@ -276,13 +291,13 @@ _exec_files_XY_all(files_backend_ptr_t be,
static nss_status_t
get_wild(files_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
{
- char *orig_id = NULL;
+ const char *orig_id = NULL;
char *old_id = NULL;
char *wild_id = NULL;
nss_status_t res = NSS_NOTFOUND;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
- orig_id = strdup(_priv_exec->id);
+ orig_id = _priv_exec->id;
old_id = strdup(_priv_exec->id);
wild_id = old_id;
while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) {
@@ -318,6 +333,7 @@ getbyid(files_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ /*LINTED*/
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYID);
@@ -336,6 +352,7 @@ getbynameid(files_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ /*LINTED*/
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
@@ -359,6 +376,7 @@ static files_backend_op_t execattr_ops[] = {
getbynameid
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_exec_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/files/common/getgrent.c b/usr/src/lib/nsswitch/files/common/getgrent.c
index 82bc1989df..6f45136f16 100644
--- a/usr/src/lib/nsswitch/files/common/getgrent.c
+++ b/usr/src/lib/nsswitch/files/common/getgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,37 +19,71 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getgrent.c -- "files" backend for nsswitch "group" database
+ * files/getgrent.c -- "files" backend for nsswitch "group" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <grp.h>
#include <unistd.h> /* for GF_PATH */
+#include <stdlib.h> /* for GF_PATH */
#include "files_common.h"
#include <strings.h>
-static u_int
-hash_grname(nss_XbyY_args_t *argp, int keyhash)
+static uint_t
+hash_grname(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen)
{
- struct group *g = argp->returnval;
- const char *name = keyhash ? argp->key.name : g->gr_name;
- u_int hash = 0;
-
- while (*name != 0)
- hash = hash * 15 + *name++;
-
+ const char *name;
+ int namelen, i;
+ uint_t hash = 0;
+
+ if (keyhash) {
+ name = argp->key.name;
+ namelen = strlen(name);
+ } else {
+ name = line;
+ namelen = 0;
+ while (linelen-- && *line++ != ':')
+ namelen++;
+ }
+
+ for (i = 0; i < namelen; i++)
+ hash = hash * 15 + name[i];
return (hash);
}
-static u_int
-hash_grgid(nss_XbyY_args_t *argp, int keyhash)
+static uint_t
+hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen)
{
- struct group *g = argp->returnval;
- return (keyhash ? (u_int)argp->key.gid : (u_int)g->gr_gid);
+ uint_t id;
+ const char *linep, *limit, *end;
+
+ linep = line;
+ limit = line + linelen;
+
+ if (keyhash)
+ return ((uint_t)argp->key.gid);
+
+ /* skip groupname */
+ while (linep < limit && *linep++ != ':');
+ /* skip password */
+ while (linep < limit && *linep++ != ':');
+ if (linep == limit)
+ return (GID_NOBODY);
+
+ /* gid */
+ end = linep;
+ id = (uint_t)strtol(linep, (char **)&end, 10);
+ /* empty gid */
+ if (linep == end)
+ return (GID_NOBODY);
+
+ return (id);
}
static files_hash_func hash_gr[2] = { hash_grname, hash_grgid };
@@ -64,15 +97,22 @@ static files_hash_t hashinfo = {
};
static int
-check_grname(argp)
- nss_XbyY_args_t *argp;
+check_grname(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct group *g = (struct group *)argp->returnval;
+ const char *linep, *limit;
+ const char *keyp = argp->key.name;
+
+ linep = line;
+ limit = line + linelen;
- /* +/- entries only valid in compat source */
- if (g->gr_name != 0 && (g->gr_name[0] == '+' || g->gr_name[0] == '-'))
+ /* +/- entries valid for compat source only */
+ if (linelen == 0 || *line == '+' || *line == '-')
return (0);
- return (strcmp(g->gr_name, argp->key.name) == 0);
+ while (*keyp && linep < limit && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (linep < limit && *keyp == '\0' && *linep == ':');
}
static nss_status_t
@@ -84,15 +124,34 @@ getbyname(be, a)
}
static int
-check_grgid(argp)
- nss_XbyY_args_t *argp;
+check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct group *g = (struct group *)argp->returnval;
+ const char *linep, *limit, *end;
+ gid_t gr_gid;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* +/- entries valid for compat source only */
+ if (linelen == 0 || *line == '+' || *line == '-')
+ return (0);
- /* +/- entries only valid in compat source */
- if (g->gr_name != 0 && (g->gr_name[0] == '+' || g->gr_name[0] == '-'))
+ /* skip username */
+ while (linep < limit && *linep++ != ':');
+ /* skip password */
+ while (linep < limit && *linep++ != ':');
+ if (linep == limit)
return (0);
- return (g->gr_gid == argp->key.gid);
+
+ /* uid */
+ end = linep;
+ gr_gid = (gid_t)strtol(linep, (char **)&end, 10);
+
+ /* empty gid is not valid */
+ if (linep == end)
+ return (0);
+
+ return (gr_gid == argp->key.gid);
}
static nss_status_t
@@ -108,7 +167,7 @@ getbymember(be, a)
files_backend_ptr_t be;
void *a;
{
- struct nss_groupsbymem *argp = (struct nss_groupsbymem *) a;
+ struct nss_groupsbymem *argp = (struct nss_groupsbymem *)a;
return (_nss_files_do_all(be, argp, argp->username,
(files_do_all_func_t)argp->process_cstr));
diff --git a/usr/src/lib/nsswitch/files/common/gethostent.c b/usr/src/lib/nsswitch/files/common/gethostent.c
index 24dd4550c1..7012cbc856 100644
--- a/usr/src/lib/nsswitch/files/common/gethostent.c
+++ b/usr/src/lib/nsswitch/files/common/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* files/gethostent.c -- "files" backend for nsswitch "hosts" database
@@ -38,33 +37,84 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
+#include <arpa/inet.h>
#include <ctype.h>
-static int check_name();
+static int check_name(nss_XbyY_args_t *, const char *, int,
+ int, const char **, int *, void *, int *);
static char *do_aliases();
-static char *strcasestr();
+static char *strcasestr(const char *as1, const char *as2);
nss_status_t __nss_files_XY_hostbyname();
int __nss_files_2herrno();
+static int __nss_files_get_addr(int, const char *, int,
+ void *, int, int *);
static int
-check_name(host, args)
- struct hostent *host;
- nss_XbyY_args_t *args;
+check_name(nss_XbyY_args_t *argp, const char *line, int linelen,
+ int type, const char **namep, int *namelen,
+ void *addrp, int *addrsize)
{
- const char *name = args->key.name;
- char **aliasp;
-
- if (!host->h_name)
- return (0);
- if (strcasecmp(host->h_name, name) == 0) {
- return (1);
+ const char *limit, *linep, *keyp, *addrstart;
+ int v6flag = 0, addrlen;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* Address */
+ addrstart = linep;
+ while (linep < limit && !isspace(*linep)) {
+ if (*linep == ':')
+ v6flag++;
+ linep++;
}
- for (aliasp = host->h_aliases; *aliasp != 0; aliasp++) {
- if (strcasecmp(*aliasp, name) == 0) {
+ addrlen = linep - addrstart;
+
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* Canonical name */
+ keyp = argp->key.name;
+ *namep = linep;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ tolower(*keyp) == tolower(*linep)) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && (linep == limit || isspace(*linep))) {
+ if (__nss_files_get_addr(type, addrstart, addrlen,
+ addrp, v6flag, addrsize)) {
+ *namelen = linep - *namep;
return (1);
}
}
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ *namelen = linep - *namep;
+
+ /* Aliases */
+ while (linep < limit) {
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* compare name (case insensitive) */
+ keyp = argp->key.name;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ tolower(*keyp) == tolower(*linep)) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && (linep == limit || isspace(*linep)))
+ return (__nss_files_get_addr(type, addrstart, addrlen,
+ addrp, v6flag, addrsize));
+
+ /* skip remainder of alias, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ }
return (0);
+
}
static nss_status_t
@@ -81,22 +131,87 @@ getbyname(be, a)
return (res);
}
+static int
+__nss_files_get_addr(int af, const char *addrstart, int addrlen,
+ void *addrp, int v6flag, int *h_length)
+{
+ struct in_addr addr_ipv4;
+ struct in6_addr *addrpv6;
+ in_addr_t *addrpv4;
+ char addrbuf[INET6_ADDRSTRLEN + 1];
+
+ if (addrlen >= sizeof (addrbuf))
+ return (0);
+ (void) memcpy(addrbuf, addrstart, addrlen);
+ addrbuf[addrlen] = '\0';
+
+ if (af == AF_INET) {
+ addrpv4 = (in_addr_t *)addrp;
+ if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU)
+ return (0);
+ *h_length = sizeof (in_addr_t);
+ } else if (af == AF_INET6) {
+ addrpv6 = (struct in6_addr *)addrp;
+ if (v6flag) {
+ if (inet_pton(af, addrbuf, addrpv6) != 1)
+ return (0);
+ } else {
+ if ((addr_ipv4.s_addr = inet_addr(addrbuf)) ==
+ 0xffffffffU)
+ return (0);
+ IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6);
+ }
+ *h_length = sizeof (struct in6_addr);
+ } else {
+ return (0);
+ }
+ return (1);
+}
+
int
-__nss_files_check_addr(argp)
- nss_XbyY_args_t *argp;
+__nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line,
+ int linelen)
{
- struct hostent *host = (struct hostent *)argp->returnval;
+ const char *limit, *linep, *addrstart;
+ int v6flag = 0, addrlen, h_length;
+ in_addr_t addr_ipv4;
+ struct in6_addr addr_ipv6;
+ char *h_addrp;
+
+ /* Compare the address type */
+ if (argp->key.hostaddr.type != af)
+ return (0);
- /*
- * We know that /etc/hosts can only store one address per host, so...
- */
- return (host->h_length == argp->key.hostaddr.len &&
- host->h_addrtype == argp->key.hostaddr.type &&
- memcmp(host->h_addr_list[0], argp->key.hostaddr.addr,
+ /* Retrieve the address */
+ if (af == AF_INET)
+ h_addrp = (char *)&addr_ipv4;
+ else
+ h_addrp = (char *)&addr_ipv6;
+ linep = line;
+ limit = line + linelen;
+ addrstart = linep;
+ while (linep < limit && !isspace(*linep)) {
+ if (*linep == ':')
+ v6flag++;
+ linep++;
+ }
+ addrlen = linep - addrstart;
+ if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp,
+ v6flag, &h_length) == 0)
+ return (0);
+
+ /* Compare the address */
+ return (h_length == argp->key.hostaddr.len &&
+ memcmp(h_addrp, argp->key.hostaddr.addr,
argp->key.hostaddr.len) == 0);
}
+static int
+check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
+{
+ return (__nss_files_check_addr(AF_INET, argp, line, linelen));
+}
static nss_status_t
getbyaddr(be, a)
@@ -106,7 +221,7 @@ getbyaddr(be, a)
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
nss_status_t res;
- res = _nss_files_XY_all(be, argp, 1, 0, __nss_files_check_addr);
+ res = _nss_files_XY_all(be, argp, 1, 0, check_addr);
if (res != NSS_SUCCESS)
argp->h_errno = __nss_files_2herrno(res);
return (res);
@@ -146,20 +261,21 @@ __nss_files_XY_hostbyname(be, args, filter, type)
const char *filter; /* hint for name string */
int type;
{
- nss_status_t res;
- int parsestat;
- char *first;
- char *last;
- int i, nhosts = 0;
- struct hostent he, *hp, *thp;
- in_addr_t taddr[MAXADDRS];
- struct in6_addr taddr6[MAXADDRS];
- char *abuf = 0; /* alias buffer */
- char *abuf_start = 0, *abuf_end;
- int (*func)();
-
- if (be->buf == 0 &&
- (be->buf = malloc(be->minbuf)) == 0) {
+ nss_status_t res;
+ char *abuf = NULL, *abuf_start = NULL, *abuf_end;
+ char *first, *last, *buffer;
+ int parsestat, i, nhosts = 0, buflen;
+ const char *namep;
+ char *h_name;
+ int h_namelen, namelen;
+ struct hostent *hp;
+ in_addr_t *taddr = NULL;
+ struct in6_addr *taddr6 = NULL;
+ size_t ntaddr;
+ void *addrp;
+ char *alias_end = NULL;
+
+ if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) {
return (NSS_UNAVAIL);
}
@@ -168,10 +284,25 @@ __nss_files_XY_hostbyname(be, args, filter, type)
return (res);
}
+ ntaddr = MAXADDRS;
+ if (type == AF_INET) {
+ taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr));
+ if (taddr == NULL)
+ return (NSS_UNAVAIL);
+ } else {
+ taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6));
+ if (taddr6 == NULL)
+ return (NSS_UNAVAIL);
+ }
+
res = NSS_NOTFOUND;
- args->erange = 0;
args->returnval = (char *)0;
- hp = thp = (struct hostent *)args->buf.result;
+ args->returnlen = 0;
+ hp = (struct hostent *)args->buf.result;
+ buffer = args->buf.buffer;
+ buflen = args->buf.buflen;
+ h_namelen = 0;
+ h_name = NULL;
for (;;) {
char *instr = be->buf;
@@ -207,83 +338,189 @@ __nss_files_XY_hostbyname(be, args, filter, type)
if (first != instr)
instr = first;
- if (nhosts && strcasestr(instr, hp->h_name) == 0) {
- break;
- }
- /*
- * If we've already matched once and have a possible match
- * on this line, copy the aliases where they're safe from
- * being overwritten when we look at the next entry. They're
- * saved as a string of blank separated names for the alias
- * parser. On errors, we return failure whether or not we
- * have already obtained a valid address.
- */
- if (nhosts == 1 && !abuf) {
- abuf = malloc(args->buf.buflen);
- if (abuf == NULL) {
- res = NSS_UNAVAIL;
- break;
- }
- abuf_start = &abuf[0];
- abuf_end = abuf_start + args->buf.buflen;
- if (abuf + strlen(hp->h_name) + 1 > abuf_end) {
- free(abuf_start);
- abuf = NULL;
- args->erange = 1;
- res = NSS_NOTFOUND;
- break;
- }
- (void) strcpy(abuf, hp->h_name);
- abuf += strlen(hp->h_name);
- *abuf++ = ' ';
- abuf = do_aliases(hp, abuf, abuf_start, abuf_end);
- if (abuf == NULL) {
- args->erange = 1;
- res = NSS_NOTFOUND;
- break;
- }
- }
- func = args->str2ent;
- parsestat = (*func)(instr, linelen, thp,
- args->buf.buffer, args->buf.buflen);
-
- if (parsestat != NSS_STR_PARSE_SUCCESS) {
- if (parsestat == NSS_STR_PARSE_ERANGE)
- args->erange = 1;
+ /* Bail out if the canonical name does not match */
+ if (nhosts && strcasestr(instr, h_name) == 0) {
continue;
}
/*
* Still need to check, strcasestr() above is just a hint.
*/
+ addrp = (type == AF_INET)?
+ (void *)&taddr[nhosts]:
+ (void *)&taddr6[nhosts];
+
+ if (check_name(args, instr, linelen,
+ type, &namep, &namelen,
+ addrp, &i)) {
- if (type == thp->h_addrtype)
- if (check_name(thp, args)) {
- if (type == AF_INET)
- taddr[nhosts++] =
- (*(in_addr_t *)thp->h_addr_list[0]);
- else {
- memcpy(&taddr6[nhosts++], thp->h_addr_list[0],
- sizeof (struct in6_addr));
+ /*
+ * If we've already matched once and have a possible
+ * match on this line, copy the aliases where they're
+ * safe from being overwritten when we look at the
+ * next entry. They're saved as a string of blank
+ * separated names for the alias parser. On errors,
+ * we return failure whether or not we have already
+ * obtained a valid address.
+ */
+ if (nhosts == 1 && hp) {
+ if (h_namelen + 1 > args->buf.buflen) {
+ args->erange = 1;
+ res = NSS_NOTFOUND;
+ break;
+ }
+ abuf = (char *)malloc(args->buf.buflen);
+ if (abuf == NULL) {
+ res = NSS_UNAVAIL;
+ break;
+ }
+ abuf_start = abuf;
+ abuf_end = abuf_start + args->buf.buflen;
+ (void) memcpy(abuf, h_name, h_namelen);
+ abuf += h_namelen;
+ *abuf = '\0';
+ abuf = do_aliases(hp, abuf, abuf_end);
+ if (abuf == NULL) {
+ args->erange = 1;
+ res = NSS_NOTFOUND;
+ break;
+ }
}
+ if (hp != NULL) {
+ /* inside the application */
+ parsestat = (*args->str2ent)(instr, linelen,
+ hp, buffer, buflen);
+ if (parsestat != NSS_STR_PARSE_SUCCESS) {
+ if (parsestat == NSS_STR_PARSE_ERANGE)
+ args->erange = 1;
+ (void) memset(buffer, 0, buflen);
+ continue;
+ }
+ } else {
+ /* inside nscd */
+ int alen, cplen, erange = 0;
+ char *ap;
+
+ /* Add alias to the first line if any */
+ if (nhosts > 0) {
+
+ /* get to the start of alias */
+ ap = (char *)namep + namelen;
+ /* see if there's any alias */
+ if (ap == instr + linelen)
+ alen = 0;
+ else
+ alen = linelen - (ap - instr);
+ if (alen + 1 >= buflen)
+ erange = 1;
+ if (erange == 0 && alen != 0) {
+ /* make room for the alias */
+ if (alias_end != NULL)
+ (void) memmove(alias_end +
+ alen, alias_end, buffer -
+ alias_end);
+ /* copy in the alias */
+ (void) memmove(alias_end,
+ ap, alen);
+ buffer += alen;
+ buflen -= alen;
+ alias_end += alen;
+ }
+
+ /* Add delimiter to the buffer */
+ *buffer++ = '\n';
+ buflen--;
+ args->returnlen++;
+ }
+
+ /* copy just the addr if not first one */
+ if (alias_end == NULL)
+ cplen = linelen;
+ else
+ cplen = namep - instr;
+
+ if (cplen >= buflen || erange == 1) {
+ args->erange = 1;
+ if (nhosts > 0) {
+ *(--buffer) = '\0';
+ buflen++;
+ args->returnlen--;
+ }
+ continue;
+ }
+
+ (void) memcpy(buffer, instr, cplen);
+ /* Adjust buffer */
+ buffer += cplen;
+ *buffer = '\0';
+ buflen -= cplen;
+ if (alias_end == NULL)
+ alias_end = buffer;
+ }
+
+ args->returnlen += linelen;
- if (nhosts == 1) {
+ /*
+ * If this is the first one, save the canonical
+ * name for future matches and continue.
+ */
+ if (++nhosts == 1) {
+ h_name = malloc(namelen + 1);
+ if (h_name == NULL) {
+ res = NSS_UNAVAIL;
+ break;
+ }
res = NSS_SUCCESS;
- args->returnval = args->buf.result;
- thp = &he; /* switch to tmp hostent */
+ (void) memcpy(h_name, namep, namelen);
+ h_name[namelen] = '\0';
+ h_namelen = namelen;
+ if (hp)
+ args->returnval = hp;
+ else
+ args->returnval = args->buf.buffer;
continue;
}
- if (nhosts >= MAXADDRS)
- break;
- abuf = do_aliases(thp, abuf, abuf_start, abuf_end);
- if (abuf == NULL) {
- args->erange = 1;
- res = NSS_NOTFOUND;
- break;
+
+
+ /* Extend the array */
+ if (nhosts >= ntaddr) {
+ ntaddr *= 2;
+ if (type == AF_INET) {
+ addrp = realloc(taddr,
+ sizeof (*taddr) * ntaddr);
+ if (addrp == NULL) {
+ res = NSS_UNAVAIL;
+ break;
+ }
+ taddr = (in_addr_t *)addrp;
+ } else {
+ addrp = realloc(taddr6,
+ sizeof (*taddr6) * ntaddr);
+ if (addrp == NULL) {
+ res = NSS_UNAVAIL;
+ break;
+ }
+ taddr6 = (struct in6_addr *)addrp;
+ }
+ }
+
+ /*
+ * For non-nscd, save aliases in a temporary buffer
+ * Don't have to do this for nscd as 'buffer' already
+ * contains the required data in the appropriate
+ * format
+ */
+ if (hp) {
+ abuf = do_aliases(hp, abuf, abuf_end);
+ if (abuf == NULL) {
+ args->erange = 1;
+ res = NSS_NOTFOUND;
+ break;
+ }
}
- } else if (abuf &&
- strcasecmp(hp->h_name, thp->h_name) == 0) {
+ } else if (namep && h_namelen == namelen &&
+ strncasecmp(h_name, namep, namelen) == 0) {
/*
* This line didn't have the requested name but
* is part of the same multihomed host (i.e. it
@@ -296,7 +533,10 @@ __nss_files_XY_hostbyname(be, args, filter, type)
}
}
- if (abuf) {
+ if (abuf && res == NSS_SUCCESS) {
+
+ /* abuf != NULL implies hp and abuf_start != NULL */
+
struct in_addr *addrp;
struct in6_addr *addrp6;
@@ -318,8 +558,8 @@ __nss_files_XY_hostbyname(be, args, filter, type)
((nhosts + 1) * sizeof (char *) +
(nhosts * sizeof (*addrp6))), sizeof (char *)));
for (i = 0, --addrp6; i < nhosts; i++, --addrp6) {
- memcpy(addrp6, &taddr6[i],
- sizeof (struct in6_addr));
+ (void) memcpy(addrp6, &taddr6[i],
+ sizeof (struct in6_addr));
hp->h_addr_list[i] = (char *)addrp6;
}
}
@@ -330,12 +570,11 @@ __nss_files_XY_hostbyname(be, args, filter, type)
(char *)hp->h_addr_list - args->buf.buffer);
if (hp->h_aliases == 0) {
args->erange = 1;
- res = NSS_STR_PARSE_ERANGE;
+ res = NSS_NOTFOUND;
} else {
hp->h_name = hp->h_aliases[0];
hp->h_aliases++;
}
- free(abuf_start);
}
/*
@@ -345,6 +584,15 @@ __nss_files_XY_hostbyname(be, args, filter, type)
if (!args->stayopen)
(void) _nss_files_endent(be, 0);
+ if (taddr)
+ free(taddr);
+ if (taddr6)
+ free(taddr6);
+ if (h_name)
+ free(h_name);
+ if (abuf_start)
+ free(abuf_start);
+
return (res);
}
@@ -352,13 +600,11 @@ __nss_files_XY_hostbyname(be, args, filter, type)
* A case-insensitive version of strstr().
*/
static char *
-strcasestr(as1, as2)
- char *as1;
- char *as2;
+strcasestr(const char *as1, const char *as2)
{
int c2;
- register char *tptr;
- register char *s1, *s2;
+ register const char *tptr;
+ register const char *s1, *s2;
s1 = as1;
s2 = as2;
@@ -383,25 +629,22 @@ strcasestr(as1, as2)
static char *
-do_aliases(hp, abuf, start, end)
- struct hostent *hp;
- char *abuf;
- char *start;
- char *end;
+do_aliases(struct hostent *hp, char *abuf, char *end)
{
- char **cp;
+ char **cp;
+ size_t len;
- for (cp = hp->h_aliases; cp && *cp && **cp; cp++) {
- size_t len;
+ if ((cp = hp->h_aliases) == NULL)
+ return (abuf);
+ for (; *cp; cp++) {
len = strlen(*cp);
if (abuf+len+1 >= end) {
- free(start);
- return ((char *)0);
+ return (NULL);
}
- (void) strcpy(abuf, *cp);
- abuf += len;
*abuf++ = ' ';
+ (void) memcpy(abuf, *cp, len);
+ abuf += len;
}
*abuf = '\0';
diff --git a/usr/src/lib/nsswitch/files/common/gethostent6.c b/usr/src/lib/nsswitch/files/common/gethostent6.c
index 22d8703848..a47f1b5f45 100644
--- a/usr/src/lib/nsswitch/files/common/gethostent6.c
+++ b/usr/src/lib/nsswitch/files/common/gethostent6.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 1988-1995, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * files/gethostent6.c -- "files" backend for nsswitch "hosts" database
+ * files/gethostent6.c -- "files" backend for nsswitch "hosts" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -42,8 +41,7 @@
extern nss_status_t __nss_files_XY_hostbyname();
extern int __nss_files_2herrno();
-extern int __nss_files_check_addr(nss_XbyY_args_t *);
-
+extern int __nss_files_check_addr(int, nss_XbyY_args_t *, const char *, int);
static nss_status_t
getbyname(be, a)
@@ -60,7 +58,11 @@ getbyname(be, a)
return (res);
}
-
+static int
+check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
+{
+ return (__nss_files_check_addr(AF_INET6, argp, line, linelen));
+}
static nss_status_t
getbyaddr(be, a)
@@ -71,13 +73,12 @@ getbyaddr(be, a)
nss_status_t res;
- res = _nss_files_XY_all(be, argp, 1, 0, __nss_files_check_addr);
+ res = _nss_files_XY_all(be, argp, 1, 0, check_addr);
if (res != NSS_SUCCESS)
argp->h_errno = __nss_files_2herrno(res);
return (res);
}
-
static files_backend_op_t ipnodes_ops[] = {
_nss_files_destr,
_nss_files_endent,
diff --git a/usr/src/lib/nsswitch/files/common/getnetent.c b/usr/src/lib/nsswitch/files/common/getnetent.c
index 992f19326c..d47b78d324 100644
--- a/usr/src/lib/nsswitch/files/common/getnetent.c
+++ b/usr/src/lib/nsswitch/files/common/getnetent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,55 +19,70 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
- *
- * files/getnetent.c -- "files" backend for nsswitch "networks" database
+ * files/getnetent.c -- "files" backend for nsswitch "networks" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netdb.h>
#include "files_common.h"
#include <strings.h>
-
-static int
-check_name(args)
- nss_XbyY_args_t *args;
-{
- struct netent *net = (struct netent *)args->returnval;
- const char *name = args->key.name;
- char **aliasp;
-
- if (strcmp(net->n_name, name) == 0)
- return (1);
- for (aliasp = net->n_aliases; *aliasp != 0; aliasp++) {
- if (strcmp(*aliasp, name) == 0)
- return (1);
- }
- return (0);
-}
+#include <ctype.h>
static nss_status_t
getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_aliases));
}
static int
-check_addr(args)
- nss_XbyY_args_t *args;
+check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct netent *net = (struct netent *)args->returnval;
- return ((net->n_addrtype == args->key.netaddr.type) &&
- (net->n_net == args->key.netaddr.net));
+ const char *limit, *linep, *addrstart;
+ int addrlen;
+ char addrbuf[NSS_LINELEN_NETWORKS];
+ in_addr_t linenet;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* skip network name */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ if (linep == limit)
+ return (0);
+
+ addrstart = linep;
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ addrlen = linep - addrstart;
+ if (addrlen < sizeof (addrbuf)) {
+ (void) memcpy(addrbuf, addrstart, addrlen);
+ addrbuf[addrlen] = '\0';
+ if ((linenet = inet_network(addrbuf)) ==
+ (in_addr_t)0xffffffffU)
+ return (0);
+ return (AF_INET == argp->key.netaddr.type &&
+ linenet == argp->key.netaddr.net);
+ }
+ return (0);
}
static nss_status_t
@@ -76,7 +90,7 @@ getbyaddr(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_files_XY_all(be, argp, 1, 0, check_addr));
}
diff --git a/usr/src/lib/nsswitch/files/common/getprinter.c b/usr/src/lib/nsswitch/files/common/getprinter.c
index c41771f8d2..8f5fab855b 100644
--- a/usr/src/lib/nsswitch/files/common/getprinter.c
+++ b/usr/src/lib/nsswitch/files/common/getprinter.c
@@ -36,140 +36,63 @@ static const char *printers = "/etc/printers.conf";
#include <stdlib.h>
#include <strings.h>
-static nss_status_t _nss_files_XY_printers(files_backend_ptr_t,
- nss_XbyY_args_t *, const char *);
-
-
-static nss_status_t
-getent(be, a)
- files_backend_ptr_t be;
- void *a;
+static int
+check_name(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, args, 0, 0, 0));
+ const char *limit, *linep;
+ const char *keyp = argp->key.name;
+ int klen = strlen(keyp);
+
+ linep = line;
+ limit = line + linelen;
+
+ /*
+ * find the name in the namelist a|b|c...:
+ */
+ while (linep+klen < limit && *linep != '|' && *linep != ':') {
+ if ((strncmp(linep, keyp, klen) == 0) &&
+ ((*(linep + klen) == '|') || (*(linep + klen) == ':'))) {
+ return (1);
+ } else {
+ while (linep < limit && *linep != '|' && *linep != ':')
+ linep++;
+ if (linep >= limit || *linep == ':')
+ return (0);
+ if (*linep == '|')
+ linep++;
+ }
+ }
+ return (0);
}
-
static nss_status_t
getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- nss_status_t res;
- /* printers_getbyname() has not set/endent; rewind on each call */
- if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) {
- return (res);
- }
- return (_nss_files_XY_printers(be, argp, argp->key.name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ check_name));
}
static files_backend_op_t printers_ops[] = {
_nss_files_destr,
_nss_files_endent,
_nss_files_setent,
- getent,
+ _nss_files_getent_rigid,
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_printers_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
{
return (_nss_files_constr(printers_ops,
- sizeof (printers_ops) / sizeof (printers_ops[0]),
- printers,
- NSS_LINELEN_PRINTERS,
- NULL));
-}
-
-/*
- * printers has the hostname as part of the data in the file, but the other
- * backends don't include it in the data passed to the backend. For this
- * reason, we process everything here and don't bother calling the backend.
- */
-static nss_status_t
-_nss_files_XY_printers(be, args, filter)
- files_backend_ptr_t be;
- nss_XbyY_args_t *args;
- const char *filter;
- /*
- * filter not useful here since the key
- * we are looking for is the first "word"
- * on the line and we can be fast enough.
- */
-{
- nss_status_t res;
- int parsestat;
- int namelen;
-
- if (be->buf == 0 &&
- (be->buf = (char *)malloc(be->minbuf)) == 0) {
- (void) _nss_files_endent(be, 0);
- return (NSS_UNAVAIL); /* really panic, malloc failed */
- }
-
- res = NSS_NOTFOUND;
- namelen = strlen(args->key.name);
-
- while (1) {
- char *instr = be->buf;
- char *p, *limit;
- int linelen;
- int found = 0;
-
- /*
- * _nss_files_read_line does process the '\' that are used
- * in /etc/printers.conf for continuation and gives one long
- * buffer.
- *
- * linelen counts the characters up to but excluding the '\n'
- */
- if ((linelen = _nss_files_read_line(be->f, instr,
- be->minbuf)) < 0) {
- /* End of file */
- args->returnval = 0;
- args->erange = 0;
- break;
- }
- p = instr;
-
- if (*p == '#') /* comment */
- continue;
-
- /*
- * find the name in the namelist a|b|c...:
- */
- if ((limit = strchr(instr, ':')) == NULL) /* bad line */
- continue;
- while ((p < limit) && (found == 0)) {
- if ((strncmp(p, args->key.name, namelen) == 0) &&
- ((*(p+namelen) == '|') || (*(p+namelen) == ':')))
- found++;
- else {
- if ((p = strchr(p, '|')) == NULL)
- p = limit;
- else /* skip the '|' */
- p++;
- }
- }
- if (found == 0)
- continue;
-
- p = instr;
-
- if (args->buf.buflen <= linelen) { /* not enough buffer */
- args->erange = 1;
- break;
- }
- (void) memcpy(args->buf.buffer, p, linelen);
- args->buf.buffer[linelen] = '\0';
- args->returnval = args->buf.result;
- res = NSS_SUCCESS;
- break;
- }
- (void) _nss_files_endent(be, 0);
- return (res);
+ sizeof (printers_ops) / sizeof (printers_ops[0]),
+ printers,
+ NSS_LINELEN_PRINTERS,
+ NULL));
}
diff --git a/usr/src/lib/nsswitch/files/common/getprofattr.c b/usr/src/lib/nsswitch/files/common/getprofattr.c
index 67c49369b0..83d4369eaa 100644
--- a/usr/src/lib/nsswitch/files/common/getprofattr.c
+++ b/usr/src/lib/nsswitch/files/common/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -35,24 +34,14 @@
* files/getprofattr.c --
* "files" backend for nsswitch "prof_attr" database
*/
-static int
-check_name(nss_XbyY_args_t *args)
-{
- profstr_t *prof = (profstr_t *)args->returnval;
- const char *name = args->key.name;
-
- if (strcmp(prof->name, name) == 0) {
- return (1);
- }
- return (0);
-}
static nss_status_t
getbyname(files_backend_ptr_t be, void *a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_colon));
}
static files_backend_op_t profattr_ops[] = {
@@ -63,6 +52,7 @@ static files_backend_op_t profattr_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_prof_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/files/common/getprojent.c b/usr/src/lib/nsswitch/files/common/getprojent.c
index cad512746c..e534760093 100644
--- a/usr/src/lib/nsswitch/files/common/getprojent.c
+++ b/usr/src/lib/nsswitch/files/common/getprojent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -29,24 +28,57 @@
#include <sys/types.h>
#include <project.h>
#include <string.h>
+#include <stdlib.h>
#include "files_common.h"
static uint_t
-hash_projname(nss_XbyY_args_t *argp, int keyhash) {
- struct project *p = argp->returnval;
- const char *name = keyhash ? argp->key.name : p->pj_name;
- uint_t hash = 0;
-
- while (*name != 0)
- hash = hash * 15 + *name++;
-
+hash_projname(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen) {
+
+ const char *name;
+ int namelen, i;
+ uint_t hash = 0;
+
+ if (keyhash) {
+ name = argp->key.name;
+ namelen = strlen(name);
+ } else {
+ name = line;
+ namelen = 0;
+ while (linelen-- && *line++ != ':')
+ namelen++;
+ }
+
+ for (i = 0; i < namelen; i++)
+ hash = hash * 15 + name[i];
return (hash);
}
static uint_t
-hash_projid(nss_XbyY_args_t *argp, int keyhash) {
- struct project *p = argp->returnval;
- return (keyhash ? (uint_t)argp->key.projid : (uint_t)p->pj_projid);
+hash_projid(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen) {
+
+ uint_t id;
+ const char *linep, *limit, *end;
+
+ linep = line;
+ limit = line + linelen;
+
+ if (keyhash)
+ return ((uint_t)argp->key.projid);
+
+ /* skip projname */
+ while (linep < limit && *linep++ != ':');
+ if (linep == limit)
+ return (0);
+
+ /* projid */
+ end = linep;
+ id = (uint_t)strtol(linep, (char **)&end, 10);
+ if (linep == end)
+ return (0);
+
+ return (id);
}
static files_hash_func hash_proj[2] = {
@@ -63,26 +95,35 @@ static files_hash_t hashinfo = {
};
static int
-check_projname(nss_XbyY_args_t *argp) {
- struct project *p = argp->returnval;
+check_projid(nss_XbyY_args_t *argp, const char *line, int linelen) {
+ projid_t projid;
+ const char *linep, *limit, *end;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* skip projname */
+ while (linep < limit && *linep++ != ':');
- if (p->pj_name == 0)
+ /* empty projname not allowed */
+ if (linep == limit || linep == line + 1)
return (0);
- return (strcmp(p->pj_name, argp->key.name) == 0);
-}
-static int
-check_projid(nss_XbyY_args_t *argp) {
- struct project *p = argp->returnval;
+ /* projid */
+ end = linep;
+ projid = (projid_t)strtol(linep, (char **)&end, 10);
- if (p->pj_name == 0)
+ /* empty projid is not valid */
+ if (linep == end)
return (0);
- return (p->pj_projid == argp->key.projid);
+
+ return (projid == argp->key.projid);
}
static nss_status_t
getbyname(files_backend_ptr_t be, void *a) {
- return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_projname));
+ return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0,
+ _nss_files_check_name_colon));
}
static nss_status_t
diff --git a/usr/src/lib/nsswitch/files/common/getprotoent.c b/usr/src/lib/nsswitch/files/common/getprotoent.c
index 25659b2e92..2f3578d13b 100644
--- a/usr/src/lib/nsswitch/files/common/getprotoent.c
+++ b/usr/src/lib/nsswitch/files/common/getprotoent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getprotoent.c -- "files" backend for nsswitch "protocols" database
+ * files/getprotoent.c -- "files" backend for nsswitch "protocols" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -31,41 +30,39 @@
#include <netdb.h>
#include "files_common.h"
#include <strings.h>
-
-static int
-check_name(args)
- nss_XbyY_args_t *args;
-{
- struct protoent *proto = (struct protoent *)args->returnval;
- const char *name = args->key.name;
- char **aliasp;
-
- if (strcmp(proto->p_name, name) == 0)
- return (1);
- for (aliasp = proto->p_aliases; *aliasp != 0; aliasp++) {
- if (strcmp(*aliasp, name) == 0)
- return (1);
- }
- return (0);
-}
+#include <ctype.h>
+#include <stdlib.h>
static nss_status_t
getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_aliases));
}
static int
-check_addr(args)
- nss_XbyY_args_t *args;
+check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct protoent *proto = (struct protoent *)args->returnval;
+ int proto;
+ const char *limit, *linep;
+
+ linep = line;
+ limit = line + linelen;
- return (proto->p_proto == args->key.number);
+ /* skip name */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ if (linep == limit)
+ return (0);
+ proto = (int)strtol(linep, NULL, 10);
+ return (proto == argp->key.number);
}
static nss_status_t
@@ -73,10 +70,10 @@ getbynumber(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char numstr[12];
- sprintf(numstr, "%d", argp->key.number);
+ (void) snprintf(numstr, 12, "%d", argp->key.number);
return (_nss_files_XY_all(be, argp, 1, 0, check_addr));
}
diff --git a/usr/src/lib/nsswitch/files/common/getpwnam.c b/usr/src/lib/nsswitch/files/common/getpwnam.c
index 303b8323c6..8faa2014eb 100644
--- a/usr/src/lib/nsswitch/files/common/getpwnam.c
+++ b/usr/src/lib/nsswitch/files/common/getpwnam.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getpwnam.c -- "files" backend for nsswitch "passwd" database
+ * files/getpwnam.c -- "files" backend for nsswitch "passwd" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -33,25 +32,60 @@
#include <unistd.h> /* for PF_PATH */
#include "files_common.h"
#include <strings.h>
+#include <stdlib.h>
-static u_int
-hash_pwname(nss_XbyY_args_t *argp, int keyhash)
+static uint_t
+hash_pwname(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen)
{
- struct passwd *p = argp->returnval;
- const char *name = keyhash ? argp->key.name : p->pw_name;
- u_int hash = 0;
-
- while (*name != 0)
- hash = hash * 15 + *name++;
-
+ const char *name;
+ int namelen, i;
+ uint_t hash = 0;
+
+ if (keyhash) {
+ name = argp->key.name;
+ namelen = strlen(name);
+ } else {
+ name = line;
+ namelen = 0;
+ while (linelen-- && *line++ != ':')
+ namelen++;
+ }
+
+ for (i = 0; i < namelen; i++)
+ hash = hash * 15 + name[i];
return (hash);
}
-static u_int
-hash_pwuid(nss_XbyY_args_t *argp, int keyhash)
+static uint_t
+hash_pwuid(nss_XbyY_args_t *argp, int keyhash, const char *line,
+ int linelen)
{
- struct passwd *p = argp->returnval;
- return (keyhash ? (u_int)argp->key.uid : (u_int)p->pw_uid);
+ uint_t id;
+ const char *linep, *limit, *end;
+
+ linep = line;
+ limit = line + linelen;
+
+ if (keyhash)
+ return ((uint_t)argp->key.uid);
+
+ /* skip username */
+ while (linep < limit && *linep++ != ':');
+ /* skip password */
+ while (linep < limit && *linep++ != ':');
+ if (linep == limit)
+ return (UID_NOBODY);
+
+ /* uid */
+ end = linep;
+ id = (uint_t)strtol(linep, (char **)&end, 10);
+
+ /* empty uid */
+ if (linep == end)
+ return (UID_NOBODY);
+
+ return (id);
}
static files_hash_func hash_pw[2] = { hash_pwname, hash_pwuid };
@@ -65,15 +99,22 @@ static files_hash_t hashinfo = {
};
static int
-check_pwname(argp)
- nss_XbyY_args_t *argp;
+check_pwname(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct passwd *p = (struct passwd *)argp->returnval;
+ const char *linep, *limit;
+ const char *keyp = argp->key.name;
+
+ linep = line;
+ limit = line + linelen;
/* +/- entries valid for compat source only */
- if (p->pw_name != 0 && (p->pw_name[0] == '+' || p->pw_name[0] == '-'))
+ if (linelen == 0 || *line == '+' || *line == '-')
return (0);
- return (strcmp(p->pw_name, argp->key.name) == 0);
+ while (*keyp && linep < limit && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (linep < limit && *keyp == '\0' && *linep == ':');
}
static nss_status_t
@@ -85,15 +126,34 @@ getbyname(be, a)
}
static int
-check_pwuid(argp)
- nss_XbyY_args_t *argp;
+check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct passwd *p = (struct passwd *)argp->returnval;
+ const char *linep, *limit, *end;
+ uid_t pw_uid;
+
+ linep = line;
+ limit = line + linelen;
/* +/- entries valid for compat source only */
- if (p->pw_name != 0 && (p->pw_name[0] == '+' || p->pw_name[0] == '-'))
+ if (linelen == 0 || *line == '+' || *line == '-')
+ return (0);
+
+ /* skip username */
+ while (linep < limit && *linep++ != ':');
+ /* skip password */
+ while (linep < limit && *linep++ != ':');
+ if (linep == limit)
return (0);
- return (p->pw_uid == argp->key.uid);
+
+ /* uid */
+ end = linep;
+ pw_uid = (uid_t)strtol(linep, (char **)&end, 10);
+
+ /* empty uid is not valid */
+ if (linep == end)
+ return (0);
+
+ return (pw_uid == argp->key.uid);
}
static nss_status_t
diff --git a/usr/src/lib/nsswitch/files/common/getrpcent.c b/usr/src/lib/nsswitch/files/common/getrpcent.c
index 789822c63c..3732c368dd 100644
--- a/usr/src/lib/nsswitch/files/common/getrpcent.c
+++ b/usr/src/lib/nsswitch/files/common/getrpcent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getrpcent.c -- "files" backend for nsswitch "rpc" database
+ * files/getrpcent.c -- "files" backend for nsswitch "rpc" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -31,43 +30,39 @@
#include <rpc/rpcent.h>
#include "files_common.h"
#include <strings.h>
-
-static int
-check_name(args)
- nss_XbyY_args_t *args;
-{
- struct rpcent *rpc = (struct rpcent *) args->returnval;
- const char *name = args->key.name;
- char **aliasp;
-
- if (strcmp(rpc->r_name, name) == 0) {
- return (1);
- }
- for (aliasp = rpc->r_aliases; *aliasp != 0; aliasp++) {
- if (strcmp(*aliasp, name) == 0) {
- return (1);
- }
- }
- return (0);
-}
+#include <ctype.h>
+#include <stdlib.h>
static nss_status_t
getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_aliases));
}
static int
-check_rpcnum(argp)
- nss_XbyY_args_t *argp;
+check_rpcnum(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct rpcent *rpc = (struct rpcent *) argp->returnval;
+ int r_number;
+ const char *limit, *linep;
+
+ linep = line;
+ limit = line + linelen;
- return (rpc->r_number == argp->key.number);
+ /* skip name */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ if (linep == limit)
+ return (0);
+ r_number = (int)strtol(linep, NULL, 10);
+ return (r_number == argp->key.number);
}
@@ -76,10 +71,10 @@ getbynumber(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char numstr[12];
- sprintf(numstr, "%d", argp->key.number);
+ (void) snprintf(numstr, 12, "%d", argp->key.number);
return (_nss_files_XY_all(be, argp, 1, numstr, check_rpcnum));
}
diff --git a/usr/src/lib/nsswitch/files/common/getservent.c b/usr/src/lib/nsswitch/files/common/getservent.c
index 855b543d55..32e73ea3f6 100644
--- a/usr/src/lib/nsswitch/files/common/getservent.c
+++ b/usr/src/lib/nsswitch/files/common/getservent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getservent.c -- "files" backend for nsswitch "services" database
+ * files/getservent.c -- "files" backend for nsswitch "services" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -32,27 +31,85 @@
#include "files_common.h"
#include <sys/types.h>
#include <netinet/in.h>
+#include <inttypes.h>
#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
static int
-check_name(args)
- nss_XbyY_args_t *args;
+check_name(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct servent *serv = (struct servent *) args->returnval;
- const char *name = args->key.serv.serv.name;
- const char *proto = args->key.serv.proto;
- char **aliasp;
+ const char *limit, *linep, *keyp;
+ int name_match = 0;
- if (proto != 0 && strcmp(serv->s_proto, proto) != 0) {
- return (0);
+ linep = line;
+ limit = line + linelen;
+ keyp = argp->key.serv.serv.name;
+
+ /* compare name */
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
}
- if (strcmp(serv->s_name, name) == 0) {
- return (1);
+ if (*keyp == '\0' && linep < limit && isspace(*linep)) {
+ if (argp->key.serv.proto == NULL)
+ return (1);
+ else
+ name_match = 1;
}
- for (aliasp = serv->s_aliases; *aliasp != 0; aliasp++) {
- if (strcmp(*aliasp, name) == 0) {
+
+ /* skip remainder of the name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* skip port number */
+ while (linep < limit && !isspace(*linep) && *linep != '/')
+ linep++;
+ if (linep == limit || *linep != '/')
+ return (0);
+
+ linep++;
+ if ((keyp = argp->key.serv.proto) == NULL) {
+ /* skip protocol */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ } else {
+ /* compare protocol */
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ /* no protocol match */
+ if (*keyp || (linep < limit && !isspace(*linep)))
+ return (0);
+ /* protocol and name match, return */
+ if (name_match)
return (1);
+ /* protocol match but name yet to be matched, so continue */
+ }
+
+ /* compare with the aliases */
+ while (linep < limit) {
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* compare with the alias name */
+ keyp = argp->key.serv.serv.name;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
}
+ if (*keyp == '\0' && (linep == limit || isspace(*linep)))
+ return (1);
+
+ /* skip remainder of the alias name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
}
return (0);
}
@@ -62,21 +119,56 @@ getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_files_XY_all(be, argp, 1,
argp->key.serv.serv.name, check_name));
}
static int
-check_port(args)
- nss_XbyY_args_t *args;
+check_port(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct servent *serv = (struct servent *) args->returnval;
- const char *proto = args->key.serv.proto;
+ const char *limit, *linep, *keyp, *numstart;
+ int numlen, s_port;
+ char numbuf[12], *numend;
+
+ linep = line;
+ limit = line + linelen;
+
+ /* skip name */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* compare port num */
+ numstart = linep;
+ while (linep < limit && !isspace(*linep) && *linep != '/')
+ linep++;
+ if (linep == limit || *linep != '/')
+ return (0);
+ numlen = linep - numstart;
+ if (numlen == 0 || numlen >= sizeof (numbuf))
+ return (0);
+ (void) memcpy(numbuf, numstart, numlen);
+ numbuf[numlen] = '\0';
+ s_port = htons((int)strtol(numbuf, &numend, 10));
+ if (*numend != '\0')
+ return (0);
+ if (s_port == argp->key.serv.serv.port) {
+ if ((keyp = argp->key.serv.proto) == NULL)
+ return (1);
+ } else
+ return (0);
- return (serv->s_port == args->key.serv.serv.port &&
- (proto == 0 || strcmp(serv->s_proto, proto) == 0));
+ /* compare protocol */
+ linep++;
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (*keyp == '\0' && (linep == limit || isspace(*linep)));
}
static nss_status_t
@@ -84,10 +176,10 @@ getbyport(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char portstr[12];
- sprintf(portstr, "%d", ntohs(argp->key.serv.serv.port));
+ (void) snprintf(portstr, 12, "%d", ntohs(argp->key.serv.serv.port));
return (_nss_files_XY_all(be, argp, 1, portstr, check_port));
}
diff --git a/usr/src/lib/nsswitch/files/common/getspent.c b/usr/src/lib/nsswitch/files/common/getspent.c
index 7287f024d2..af280b6d74 100644
--- a/usr/src/lib/nsswitch/files/common/getspent.c
+++ b/usr/src/lib/nsswitch/files/common/getspent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * files/getspent.c -- "files" backend for nsswitch "shadow" database
+ * files/getspent.c -- "files" backend for nsswitch "shadow" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -33,15 +32,19 @@
#include <strings.h>
static int
-check_spnamp(argp)
- nss_XbyY_args_t *argp;
+check_spnamp(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct spwd *s = (struct spwd *)argp->returnval;
+ const char *linep = line;
+ const char *keyp = argp->key.name;
- /* +/- entries valid in compat source only */
- if (s->sp_namp != 0 && (s->sp_namp[0] == '+' || s->sp_namp[0] == '-'))
+ /* +/- entries valid for compat source only */
+ if (linelen == 0 || *line == '+' || *line == '-')
return (0);
- return (strcmp(s->sp_namp, argp->key.name) == 0);
+ while (*keyp && linelen-- && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (linelen && *keyp == '\0' && *linep == ':');
}
static nss_status_t
@@ -49,7 +52,7 @@ getbyname(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_files_XY_all(be, argp, 0, argp->key.name, check_spnamp));
}
diff --git a/usr/src/lib/nsswitch/files/common/getuserattr.c b/usr/src/lib/nsswitch/files/common/getuserattr.c
index 82f377c5da..3ada2a420f 100644
--- a/usr/src/lib/nsswitch/files/common/getuserattr.c
+++ b/usr/src/lib/nsswitch/files/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -35,24 +34,14 @@
* files/getuserattr.c --
* "files" backend for nsswitch "user_attr" database
*/
-static int
-check_name(nss_XbyY_args_t *args)
-{
- userstr_t *user = (userstr_t *)args->returnval;
- const char *name = args->key.name;
-
- if (strcmp(user->name, name) == 0) {
- return (1);
- }
- return (0);
-}
static nss_status_t
getbyname(files_backend_ptr_t be, void *a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name,
+ _nss_files_check_name_colon));
}
static files_backend_op_t userattr_ops[] = {
@@ -63,6 +52,7 @@ static files_backend_op_t userattr_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_files_user_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/files/common/netmasks.c b/usr/src/lib/nsswitch/files/common/netmasks.c
index 876fcf66a6..2fe4a2fe1b 100644
--- a/usr/src/lib/nsswitch/files/common/netmasks.c
+++ b/usr/src/lib/nsswitch/files/common/netmasks.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * files/netmasks.c -- "files" backend for nsswitch "netmasks" database
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * Copyright (c) 1996 Sun Microsystems Inc
- * All Rights Reserved.
+ * files/netmasks.c -- "files" backend for nsswitch "netmasks" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -43,20 +42,45 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <nss_dbdefs.h>
+#include <ctype.h>
/*
* Validate 'files' netmasks entry. The comparison objects are in IPv4
* internet address format.
*/
static int
-check_addr(args)
- nss_XbyY_args_t *args;
+check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
{
- struct in_addr tmp;
+ const char *limit, *linep, *addrstart;
+ int addrlen;
+ char addrbuf[NSS_LINELEN_NETMASKS];
+ struct in_addr lineaddr, argsaddr;
- tmp.s_addr = inet_addr(args->key.name);
- return (memcmp(args->buf.buffer, (char *)&tmp,
- sizeof (struct in_addr)) == 0);
+ linep = line;
+ limit = line + linelen;
+
+ /* skip leading spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ addrstart = linep;
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ if (linep == limit)
+ return (0);
+ addrlen = linep - addrstart;
+ if (addrlen < sizeof (addrbuf)) {
+ (void) memcpy(addrbuf, addrstart, addrlen);
+ addrbuf[addrlen] = '\0';
+ if ((lineaddr.s_addr = inet_addr(addrbuf)) ==
+ (in_addr_t)0xffffffffU)
+ return (0);
+ if ((argsaddr.s_addr = inet_addr(argp->key.name))
+ == (in_addr_t)0xffffffffU)
+ return (0);
+ return (lineaddr.s_addr == argsaddr.s_addr);
+ }
+ return (0);
}
static nss_status_t
@@ -64,15 +88,46 @@ getbynet(be, a)
files_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
nss_status_t res;
char tmpbuf[NSS_LINELEN_NETMASKS];
- argp->buf.buffer = tmpbuf;
- argp->buf.buflen = NSS_LINELEN_NETMASKS;
+ /*
+ * use the buffer passed in if result is to be returned
+ * in /etc file format
+ */
+ if (argp->buf.result != NULL) {
+ argp->buf.buffer = tmpbuf;
+ argp->buf.buflen = NSS_LINELEN_NETMASKS;
+ }
res = _nss_files_XY_all(be, argp, 0, argp->key.name, check_addr);
- argp->buf.buffer = NULL;
- argp->buf.buflen = 0;
+ if (argp->buf.result != NULL) {
+ argp->buf.buffer = NULL;
+ argp->buf.buflen = 0;
+ } else {
+ /* the frontend expects the netmask data only */
+ if (res == NSS_SUCCESS) {
+ char *m;
+ char *s = (char *)argp->returnval;
+ int l = 0;
+
+ m = s + argp->returnlen - 1;
+
+ /* skip trailing spaces */
+ while (s < m && isspace(*m))
+ m--;
+
+ for (; s <= m; m--) {
+ if (isspace(*m))
+ break;
+ l++;
+ }
+ m++;
+ (void) memmove(argp->returnval, m, l);
+ argp->returnlen = l;
+ *(s + l) = '\0';
+ }
+ }
return (res);
}
diff --git a/usr/src/lib/nsswitch/files/common/tsol_getrhent.c b/usr/src/lib/nsswitch/files/common/tsol_getrhent.c
index f41f606034..180a660189 100644
--- a/usr/src/lib/nsswitch/files/common/tsol_getrhent.c
+++ b/usr/src/lib/nsswitch/files/common/tsol_getrhent.c
@@ -28,30 +28,102 @@
#include "files_common.h"
#include <string.h>
#include <libtsnet.h>
+#include <netinet/in.h>
/*
* files/tsol_getrhent.c --
* "files" backend for nsswitch "tnrhdb" database
*/
static int
-check_addr(nss_XbyY_args_t *args)
+check_addr(nss_XbyY_args_t *args, const char *line, int linelen)
{
- tsol_rhstr_t *rhstrp = (tsol_rhstr_t *)args->returnval;
+ const char *limit, *linep, *keyp;
+ char prev;
+ int ipv6;
- if ((args->key.hostaddr.type == rhstrp->family) &&
- (strcmp(args->key.hostaddr.addr, rhstrp->address) == 0))
+ linep = line;
+ limit = line + linelen;
+ keyp = args->key.hostaddr.addr;
+ prev = '\0';
+
+ if (strstr(linep, "\\:") != NULL)
+ ipv6 = 1;
+ else
+ ipv6 = 0;
+
+ /*
+ * compare addr in
+ *
+ * 192.168.120.6:public
+ * fec0\:\:a00\:20ff\:fea0\:21f7:cipso
+ *
+ * ':' is the seperator.
+ */
+
+ while (*keyp && linep < limit && *keyp == *linep) {
+ if ((ipv6 == 0 && *linep == ':') ||
+ (ipv6 == 1 && prev != '\\' && *linep == ':'))
+ break;
+
+ prev = *linep;
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && linep < limit && ((ipv6 == 0 && *linep == ':') ||
+ (ipv6 == 1 && prev != '\\' && *linep == ':')))
return (1);
return (0);
}
+static void
+escape_colon(const char *in, char *out) {
+ int i, j;
+ for (i = 0, j = 0; in[i] != '\0'; i++) {
+ if (in[i] == ':') {
+ out[j++] = '\\';
+ out[j++] = in[i];
+ } else
+ out[j++] = in[i];
+ }
+ out[j] = '\0';
+}
+
static nss_status_t
getbyaddr(files_backend_ptr_t be, void *a)
{
nss_XbyY_args_t *argp = a;
+ char addr6[INET6_ADDRSTRLEN + 5]; /* 5 '\' for ':' */
+ const char *addr = NULL;
+ nss_status_t rc;
+
+ if (argp->key.hostaddr.addr == NULL ||
+ (argp->key.hostaddr.type != AF_INET &&
+ argp->key.hostaddr.type != AF_INET6))
+ return (NSS_NOTFOUND);
+ if (strchr(argp->key.hostaddr.addr, ':') != NULL) {
+ /* IPV6 */
+ if (argp->key.hostaddr.type == AF_INET)
+ return (NSS_NOTFOUND);
+ escape_colon(argp->key.hostaddr.addr, addr6);
+ /* save the key in original format */
+ addr = argp->key.hostaddr.addr;
+ /* Replace the key with escaped format */
+ argp->key.hostaddr.addr = addr6;
+ } else {
+ /* IPV4 */
+ if (argp->key.hostaddr.type == AF_INET6)
+ return (NSS_NOTFOUND);
+ }
+
+ rc = _nss_files_XY_all(be, argp, 1,
+ argp->key.hostaddr.addr, check_addr);
+
+ /* restore argp->key.hostaddr.addr */
+ if (addr)
+ argp->key.hostaddr.addr = addr;
- return (_nss_files_XY_all(be, argp, 1,
- argp->key.hostaddr.addr, check_addr));
+ return (rc);
}
static files_backend_op_t tsol_rh_ops[] = {
@@ -62,9 +134,10 @@ static files_backend_op_t tsol_rh_ops[] = {
getbyaddr
};
-/* ARGSUSED */
nss_backend_t *
+/* LINTED E_FUNC_ARG_UNUSED */
_nss_files_tnrhdb_constr(const char *dummy1, const char *dummy2,
+/* LINTED E_FUNC_ARG_UNUSED */
const char *dummy3)
{
return (_nss_files_constr(tsol_rh_ops,
diff --git a/usr/src/lib/nsswitch/files/common/tsol_gettpent.c b/usr/src/lib/nsswitch/files/common/tsol_gettpent.c
index ae5e9ca2be..dd604a5ee9 100644
--- a/usr/src/lib/nsswitch/files/common/tsol_gettpent.c
+++ b/usr/src/lib/nsswitch/files/common/tsol_gettpent.c
@@ -34,12 +34,20 @@
* "files" backend for nsswitch "tnrhtp" database
*/
static int
-check_name(nss_XbyY_args_t *args)
+check_name(nss_XbyY_args_t *args, const char *line, int linelen)
{
- tsol_tpstr_t *tpstrp = (tsol_tpstr_t *)args->returnval;
- const char *name = args->key.name;
+ const char *limit, *linep, *keyp;
- if (strcmp(tpstrp->template, name) == 0)
+ linep = line;
+ limit = line + linelen;
+ keyp = args->key.name;
+
+ /* compare template name, ':' is the seperator */
+ while (*keyp && linep < limit && *linep != ':' && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && linep < limit && *linep == ':')
return (1);
return (0);
@@ -52,6 +60,9 @@ getbyname(be, a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ if (argp->key.name == NULL)
+ return (NSS_NOTFOUND);
+
return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
}
@@ -62,8 +73,8 @@ static files_backend_op_t tsol_tp_ops[] = {
_nss_files_getent_netdb,
getbyname
};
-
nss_backend_t *
+/* LINTED E_FUNC_ARG_UNUSED */
_nss_files_tnrhtp_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
{
diff --git a/usr/src/lib/nsswitch/ldap/Makefile.com b/usr/src/lib/nsswitch/ldap/Makefile.com
index 031dd04f46..43779514fc 100644
--- a/usr/src/lib/nsswitch/ldap/Makefile.com
+++ b/usr/src/lib/nsswitch/ldap/Makefile.com
@@ -62,4 +62,6 @@ include ../../Makefile.com
CPPFLAGS += -I../../../libsldap/common
LDLIBS += -lsldap -lnsl -lsocket -lldap
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+LINTFLAGS64 += -erroff=E_GLOBAL_COULD_BE_STATIC2
DYNLIB1 = nss_ldap.so$(VERS)
diff --git a/usr/src/lib/nsswitch/ldap/common/getauthattr.c b/usr/src/lib/nsswitch/ldap/common/getauthattr.c
index ea3341bf57..7b7b0c38b2 100644
--- a/usr/src/lib/nsswitch/ldap/common/getauthattr.c
+++ b/usr/src/lib/nsswitch/ldap/common/getauthattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,170 +50,94 @@ static const char *auth_attrs[] = {
_AUTH_ATTRS,
(char *)NULL
};
-
-
+/*
+ * _nss_ldap_auth2str is the data marshaling method for the auth_attr
+ * system call getauthattr and getauthnam.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * solaris.:::All Solaris Authorizations::help=AllSolAuthsHeader.html
+ *
+ */
static int
-_nss_ldap_auth2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_auth2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
- int buflen = (int)0;
+ int nss_result;
+ int buflen = 0;
unsigned long len = 0L;
- char *nullstring = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- authstr_t *auth = (authstr_t *)NULL;
- ns_ldap_attr_t *attrptr;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
+ char **name, **res1, **res2, **sdes, **ldes, **attr;
+ char *res1_str, *res2_str, *sdes_str, *ldes_str;
+ char *attr_str;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- auth = (authstr_t *)(argp->buf.result);
- ceiling = buffer + buflen;
- auth->name = (char *)NULL;
- auth->res1 = (char *)NULL;
- auth->res2 = (char *)NULL;
- auth->short_desc = (char *)NULL;
- auth->long_desc = (char *)NULL;
- auth->attr = (char *)NULL;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_auth2ent;
- }
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_auth2ent;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_NAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_auth2ent;
- }
- auth->name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_RES1) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- auth->res1 = nullstring;
- } else {
- auth->res1 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->res1,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_RES2) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- auth->res2 = nullstring;
- } else {
- auth->res2 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->res2,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_SHORTDES) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- auth->short_desc = nullstring;
- } else {
- auth->short_desc = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->short_desc,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_LONGDES) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- auth->long_desc = nullstring;
- } else {
- auth->long_desc = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->long_desc,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AUTH_ATTRS) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- auth->attr = nullstring;
- } else {
- auth->attr = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_auth2ent;
- }
- (void) strcpy(auth->attr,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- }
+ buflen = argp->buf.buflen;
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getauthattr.c: _nss_ldap_auth2ent]\n");
- (void) fprintf(stdout, " auth-name: [%s]\n", auth->name);
- if (auth->res1 != (char *)NULL) {
- (void) fprintf(stdout, " res1: [%s]\n", auth->res1);
- }
- if (auth->res2 != (char *)NULL) {
- (void) fprintf(stdout, " res2: [%s]\n", auth->res2);
- }
- if (auth->short_desc != (char *)NULL) {
- (void) fprintf(stdout, " short_desc: [%s]\n",
- auth->short_desc);
+ name = __ns_ldap_getAttr(result->entry, _AUTH_NAME);
+ if (name == NULL || name[0] == NULL ||
+ (strlen(name[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_auth2str;
}
- if (auth->long_desc != (char *)NULL) {
- (void) fprintf(stdout, " long_desc: [%s]\n",
- auth->long_desc);
+ res1 = __ns_ldap_getAttr(result->entry, _AUTH_RES1);
+ if (res1 == NULL || res1[0] == NULL || (strlen(res1[0]) < 1))
+ res1_str = _NO_VALUE;
+ else
+ res1_str = res1[0];
+
+ res2 = __ns_ldap_getAttr(result->entry, _AUTH_RES2);
+ if (res2 == NULL || res2[0] == NULL || (strlen(res2[0]) < 1))
+ res2_str = _NO_VALUE;
+ else
+ res2_str = res2[0];
+
+ sdes = __ns_ldap_getAttr(result->entry, _AUTH_SHORTDES);
+ if (sdes == NULL || sdes[0] == NULL || (strlen(sdes[0]) < 1))
+ sdes_str = _NO_VALUE;
+ else
+ sdes_str = sdes[0];
+
+ ldes = __ns_ldap_getAttr(result->entry, _AUTH_LONGDES);
+ if (ldes == NULL || ldes[0] == NULL || (strlen(ldes[0]) < 1))
+ ldes_str = _NO_VALUE;
+ else
+ ldes_str = ldes[0];
+
+ attr = __ns_ldap_getAttr(result->entry, _AUTH_ATTRS);
+ if (attr == NULL || attr[0] == NULL || (strlen(attr[0]) < 1))
+ attr_str = _NO_VALUE;
+ else
+ attr_str = attr[0];
+ /* 6 = 5 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(res1_str) + strlen(res2_str) +
+ strlen(sdes_str) + strlen(ldes_str) + strlen(attr_str) + 6;
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_auth2str;
}
- if (auth->attr != (char *)NULL) {
- (void) fprintf(stdout, " attr: [%s]\n", auth->attr);
- }
-#endif /* DEBUG */
-result_auth2ent:
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_auth2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+ (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s",
+ name[0], res1_str, res2_str, sdes_str,
+ ldes_str, attr_str);
+ /* The front end marshaller doesn't need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_auth2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
@@ -229,10 +152,6 @@ getbyname(ldap_backend_ptr be, void *a)
char name[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getauthattr.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -268,11 +187,7 @@ _nss_ldap_auth_attr_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[getauthattr.c: _nss_ldap_auth_attr_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(authattr_ops,
sizeof (authattr_ops)/sizeof (authattr_ops[0]), _AUTHATTR,
- auth_attrs, _nss_ldap_auth2ent));
+ auth_attrs, _nss_ldap_auth2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getauuser.c b/usr/src/lib/nsswitch/ldap/common/getauuser.c
index 2267b22ba9..7c9d9431c5 100644
--- a/usr/src/lib/nsswitch/ldap/common/getauuser.c
+++ b/usr/src/lib/nsswitch/ldap/common/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -45,109 +44,73 @@ static const char *auuser_attrs[] = {
_AU_NEVER,
(char *)NULL
};
-
-
+/*
+ * _nss_ldap_au2str is the data marshaling method for the audit_user
+ * system call getauusernam, getauusernam_r, getauuserent and getauuserent_r.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * root:lo:no
+ *
+ */
static int
-_nss_ldap_au2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_au2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
- int buflen = (int)0;
+ int nss_result;
+ int buflen = 0;
unsigned long len = 0L;
- char *nullstring = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- au_user_str_t *au_user = (au_user_str_t *)NULL;
- ns_ldap_attr_t *attrptr;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
+ char **name, **al, **ne, *al_str, *ne_str;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_au2ent;
- }
- au_user = (au_user_str_t *)(argp->buf.result);
- ceiling = buffer + buflen;
- au_user->au_name = (char *)NULL;
- au_user->au_always = (char *)NULL;
- au_user->au_never = (char *)NULL;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_au2ent;
- }
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_au2ent;
- }
- if (strcasecmp(attrptr->attrname, _AU_NAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_au2ent;
- }
- au_user->au_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_au2ent;
- }
- (void) strcpy(au_user->au_name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AU_ALWAYS) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- au_user->au_always = nullstring;
- } else {
- au_user->au_always = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_au2ent;
- }
- (void) strcpy(au_user->au_always,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _AU_NEVER) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- au_user->au_never = nullstring;
- } else {
- au_user->au_never = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_au2ent;
- }
- (void) strcpy(au_user->au_never,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- }
+ buflen = argp->buf.buflen;
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getauuser.c: _nss_ldap_au2ent]\n");
- (void) fprintf(stdout, " au_name: [%s]\n", au_user->au_name);
- if (au_user->au_always != (char *)NULL) {
- (void) fprintf(stdout, " au_always: [%s]\n",
- au_user->au_always);
+ name = __ns_ldap_getAttr(result->entry, _AU_NAME);
+ if (name == NULL || name[0] == NULL ||
+ (strlen(name[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_au2str;
}
- if (au_user->au_never != (char *)NULL) {
- (void) fprintf(stdout, " au_never: [%s]\n",
- au_user->au_never);
+ al = __ns_ldap_getAttr(result->entry, _AU_ALWAYS);
+ if (al == NULL || al[0] == NULL || (strlen(al[0]) < 1))
+ al_str = _NO_VALUE;
+ else
+ al_str = al[0];
+
+ ne = __ns_ldap_getAttr(result->entry, _AU_NEVER);
+ if (ne == NULL || ne[0] == NULL || (strlen(ne[0]) < 1))
+ ne_str = _NO_VALUE;
+ else
+ ne_str = ne[0];
+
+ /* 3 = 2 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(al_str) + strlen(ne_str) + 3;
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_au2str;
}
-#endif /* DEBUG */
-result_au2ent:
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_au2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+ (void) snprintf(buffer, len, "%s:%s:%s",
+ name[0], al_str, ne_str);
+ /* The front end marshaller doesn't need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_au2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
@@ -162,10 +125,6 @@ getbyname(ldap_backend_ptr be, void *a)
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getauuser.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -203,11 +162,7 @@ _nss_ldap_audit_user_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[getauuser.c: _nss_ldap_audit_user_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(auuser_ops,
sizeof (auuser_ops)/sizeof (auuser_ops[0]), _AUUSER,
- auuser_attrs, _nss_ldap_au2ent));
+ auuser_attrs, _nss_ldap_au2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getbootparams.c b/usr/src/lib/nsswitch/ldap/common/getbootparams.c
index f1426ba4b6..6a5c05d132 100644
--- a/usr/src/lib/nsswitch/ldap/common/getbootparams.c
+++ b/usr/src/lib/nsswitch/ldap/common/getbootparams.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,85 +40,83 @@ static const char *bootparams_attrs[] = {
};
/*
- * _nss_ldap_bootparams2ent is the data marshaling method for the
- * bootparams getXbyY (e.g., getbyname()) backend processes. This
- * method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into argp->buf.buffer
- * Three error conditions are expected and returned to nsswitch.
+ * _nss_ldap_bootparams2str is the data marshaling method for the
+ * bootparams bootparams_getbyname backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into the file format.
*
* A host's bootparameters are returned on one line separated by white
- * space. Slapd stores each boot parameter as a separate entry. If more
- * than one bootparameter is available, a white space separated buffer
+ * space. The LDAP server stores each boot parameter as a separate entry.
+ * If more than one bootparameter is available, a white space separated buffer
* must be constructed and returned.
+ *
*/
static int
-_nss_ldap_bootparams2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_bootparams2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j, nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char *cp = (char *)NULL;
- char *buffer = (char *)NULL;
+ uint_t i;
+ int buflen = 0, len = 0;
+ int nss_result, firsttime;
+ ns_ldap_attr_t *bparams;
+ char *buffer, **names;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
-
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_bp2ent;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = argp->buf.buflen;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_bp2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ names = __ns_ldap_getAttr(result->entry, _B_HOSTNAME);
+ if (names == NULL || names[0] == NULL ||
+ (strlen(names[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_bp2str;
}
-
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_bp2ent;
+ bparams = __ns_ldap_getAttrStruct(result->entry, _B_PARAMETER);
+ if (bparams == NULL || bparams->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_bp2str;
+ }
+ firsttime = 1;
+ for (i = 0; i < bparams->value_count; i++) {
+ if (bparams->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_bp2str;
}
- if (strcasecmp(attrptr->attrname, _B_PARAMETER) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- *buffer = 0;
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_bp2ent;
- }
- if (len > buflen) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_bp2ent;
- }
- if (firstime) {
- (void) strcpy(buffer,
- attrptr->attrvalue[j]);
- firstime = (int)0;
- } else {
- if ((cp = strrchr(buffer, '\0'))
- != NULL)
- *cp = ' ';
- (void) strcat(buffer,
- attrptr->attrvalue[j]);
- }
- }
+ /*
+ * Skip client host name. The early version of ldapaddent
+ * adds hostname as a boot param and it should be filtered.
+ */
+ if (strcasecmp(names[0], bparams->attrvalue[i]) != 0) {
+ if (firsttime) {
+ firsttime = 0;
+ len = snprintf(buffer, buflen, "%s",
+ bparams->attrvalue[i]);
+ } else
+ len = snprintf(buffer, buflen, " %s",
+ bparams->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_bp2str);
}
}
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[bootparams_getbyname.c: "
- "_nss_ldap_bootparams2ent]\n");
- (void) fprintf(stdout, " bootparameter: [%s]\n", buffer);
-#endif /* DEBUG */
-
-result_bp2ent:
+result_bp2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
/*
@@ -156,7 +153,6 @@ getbyname(ldap_backend_ptr be, void *a)
_F_GETBOOTPARAMBYNAME_SSD, hostname);
if (ret >= sizeof (userdata) || ret < 0)
return ((nss_status_t)NSS_NOTFOUND);
-
return ((nss_status_t)_nss_ldap_lookup(be, argp,
_BOOTPARAMS, searchfilter, NULL,
_merge_SSD_filter, userdata));
@@ -183,5 +179,5 @@ _nss_ldap_bootparams_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(bootparams_ops,
sizeof (bootparams_ops)/sizeof (bootparams_ops[0]),
- _BOOTPARAMS, bootparams_attrs, _nss_ldap_bootparams2ent));
+ _BOOTPARAMS, bootparams_attrs, _nss_ldap_bootparams2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getether.c b/usr/src/lib/nsswitch/ldap/common/getether.c
index 01f337dea8..9ce919853b 100644
--- a/usr/src/lib/nsswitch/ldap/common/getether.c
+++ b/usr/src/lib/nsswitch/ldap/common/getether.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,131 +47,58 @@ static const char *ethers_attrs[] = {
(char *)NULL
};
-
/*
- * _nss_ldap_ethers2ent is the data marshaling method for the ethers
- * getXbyY * (e.g., getbyhost(), getbyether()) backend processes. This
- * method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into uchar_t *ether
- * = argp->buf.buffer which the frontend process expects. Three error
- * conditions are expected and returned to nsswitch.
- *
- * Place the resulting struct ether_addr from the ldap query into
- * argp->buf.result only if argp->buf.result is initialized (not NULL).
- * e.g., it happens for the call ether_hostton.
+ * _nss_ldap_ethers2str is the data marshaling method for the ethers
+ * ether_hostton/ether_ntohost backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into the file format.
+ * e.g.
*
- * Place the resulting hostname into argp->buf.buffer only if
- * argp->buf.buffer is initialized. I.e. it happens for the call
- * ether_ntohost.
+ * 8:0:20:8e:eb:8a8 borealis
*
- * argp->buf.buflen does not make sense for ethers. It is always set
- * to 0 by the frontend. The caller only passes a hostname pointer in
- * case of ether_ntohost, that is assumed to be big enough. For
- * ether_hostton, the struct ether_addr passed is a fixed size.
+ * The front end marshaller str2ether uses argp->buf.result for a different
+ * purpose so a flag be->db_type is set to work around this oddity.
*
- * The interface does not let the caller specify how long is the buffer
- * pointed by host. We make a safe assumption that the callers will
- * always give MAXHOSTNAMELEN. In any case, it is the only finite number
- * we can lay our hands on in case of runaway strings, memory corruption etc.
*/
-
+/*ARGSUSED0*/
static int
-_nss_ldap_ethers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_ethers2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, ip;
int nss_result;
- int buflen = (int)0;
- unsigned int t[ETHERADDRL];
- unsigned long len = 0L;
- char *host = NULL;
- struct ether_addr *ether = NULL;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
- int etherflag = 0, hostflag = 0;
+ char **host, **macaddress;
- if (argp->buf.buffer) {
- hostflag = 1;
- host = argp->buf.buffer;
- }
-
- buflen = (size_t)argp->buf.buflen;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ nss_result = NSS_STR_PARSE_SUCCESS;
- if (argp->buf.result) {
- etherflag = 1;
- ether = (struct ether_addr *)argp->buf.result;
+ host = __ns_ldap_getAttr(result->entry, _E_HOSTNAME);
+ if (host == NULL || host[0] == NULL || (strlen(host[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_ea2str;
}
-
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_ea2ent;
+ macaddress = __ns_ldap_getAttr(result->entry, _E_MACADDRESS);
+ if (macaddress == NULL || macaddress[0] == NULL ||
+ (strlen(macaddress[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_ea2str;
}
-
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_ea2ent;
- }
- if (hostflag) {
- if (strcasecmp(attrptr->attrname, _E_HOSTNAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_ea2ent;
- }
- if (len > MAXHOSTNAMELEN) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_ea2ent;
- }
- (void) strcpy(host, attrptr->attrvalue[0]);
- continue;
- }
- }
- if (etherflag) {
- if (strcasecmp(attrptr->attrname, _E_MACADDRESS) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_ea2ent;
- }
- ip = (int)sscanf(attrptr->attrvalue[0],
- "%x:%x:%x:%x:%x:%x", &t[0], &t[1],
- &t[2], &t[3], &t[4], &t[5]);
- if (ip != ETHERADDRL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_ea2ent;
- }
- for (ip = 0; ip < ETHERADDRL; ip++)
- ether->ether_addr_octet[ip] =
- (uchar_t)t[ip];
- continue;
- }
- }
+ be->buflen = strlen(host[0]) + strlen(macaddress[0]) + 1; /* ' ' */
+ /* Add a trailing null for easy debug */
+ be->buffer = calloc(1, be->buflen + 1);
+ if (be->buffer == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_ea2str;
}
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[ether_addr.c: _nss_ldap_ethers2ent]\n");
- if (host != NULL)
- (void) fprintf(stdout, " hostname: [%s]\n", host);
- if (ether != NULL)
- (void) fprintf(stdout,
- " ether_addr: [%x:%x:%x:%x:%x:%x]\n",
- ether->ether_addr_octet[0],
- ether->ether_addr_octet[1],
- ether->ether_addr_octet[2],
- ether->ether_addr_octet[3],
- ether->ether_addr_octet[4],
- ether->ether_addr_octet[5]);
-#endif /* DEBUG */
-
-result_ea2ent:
+ (void) snprintf(be->buffer, be->buflen + 1, "%s %s",
+ macaddress[0], host[0]);
+ be->db_type = NSS_LDAP_DB_ETHERS;
+
+result_ea2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
/*
@@ -197,23 +123,28 @@ getbyhost(ldap_backend_ptr be, void *a)
char searchfilter[SEARCHFILTERLEN];
char userdata[SEARCHFILTERLEN];
int ret;
+ nss_status_t rc;
if (_ldap_filter_name(hostname, argp->key.name, sizeof (hostname)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
ret = snprintf(searchfilter, sizeof (searchfilter),
_F_GETETHERBYHOST, hostname);
+
if (ret >= sizeof (searchfilter) || ret < 0)
return ((nss_status_t)NSS_NOTFOUND);
ret = snprintf(userdata, sizeof (userdata),
_F_GETETHERBYHOST_SSD, hostname);
+
if (ret >= sizeof (userdata) || ret < 0)
return ((nss_status_t)NSS_NOTFOUND);
- return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ rc = (nss_status_t)_nss_ldap_lookup(be, argp,
_ETHERS, searchfilter, NULL,
- _merge_SSD_filter, userdata));
+ _merge_SSD_filter, userdata);
+
+ return (rc);
}
@@ -279,5 +210,5 @@ _nss_ldap_ethers_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(ethers_ops,
sizeof (ethers_ops)/sizeof (ethers_ops[0]), _ETHERS,
- ethers_attrs, _nss_ldap_ethers2ent));
+ ethers_attrs, _nss_ldap_ethers2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getexecattr.c b/usr/src/lib/nsswitch/ldap/common/getexecattr.c
index 4dfedc8628..35a60e579d 100644
--- a/usr/src/lib/nsswitch/ldap/common/getexecattr.c
+++ b/usr/src/lib/nsswitch/ldap/common/getexecattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -262,29 +261,94 @@ _exec_ldap_exec2ent(ns_ldap_entry_t *entry, nss_XbyY_args_t *argp)
/*
- * place the results from ldap object structure into argp->buf.result
+ * place the results from ldap object structure into the file format
* returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-_nss_ldap_exec2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_exec2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int status = (int)NSS_STR_PARSE_SUCCESS;
- ns_ldap_entry_t *entry;
+ int status = NSS_STR_PARSE_SUCCESS;
ns_ldap_result_t *result = be->result;
-
- if (!argp->buf.result) {
- status = (int)NSS_STR_PARSE_ERANGE;
- goto result_exec2ent;
+ int len;
+ char *buffer, **name, **policy, **type;
+ char **res1, **res2, **id, **attr;
+ char *policy_str, *type_str, *res1_str, *res2_str;
+ char *id_str, *attr_str;
+
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+
+ (void) memset(argp->buf.buffer, 0, argp->buf.buflen);
+
+ name = __ns_ldap_getAttr(result->entry, _EXEC_NAME);
+ if (name == NULL || name[0] == NULL ||
+ (strlen(name[0]) < 1)) {
+ status = NSS_STR_PARSE_PARSE;
+ goto result_exec2str;
}
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- status = _exec_ldap_exec2ent(entry, argp);
- if (status != NSS_STR_PARSE_SUCCESS) {
- goto result_exec2ent;
- }
+ policy = __ns_ldap_getAttr(result->entry, _EXEC_POLICY);
+
+ if (policy == NULL || policy[0] == NULL)
+ policy_str = _NO_VALUE;
+ else
+ policy_str = policy[0];
+
+ type = __ns_ldap_getAttr(result->entry, _EXEC_TYPE);
+ if (type == NULL || type[0] == NULL)
+ type_str = _NO_VALUE;
+ else
+ type_str = type[0];
+
+ res1 = __ns_ldap_getAttr(result->entry, _EXEC_RES1);
+ if (res1 == NULL || res1[0] == NULL)
+ res1_str = _NO_VALUE;
+ else
+ res1_str = res1[0];
+
+ res2 = __ns_ldap_getAttr(result->entry, _EXEC_RES2);
+ if (res2 == NULL || res2[0] == NULL)
+ res2_str = _NO_VALUE;
+ else
+ res2_str = res2[0];
+
+ id = __ns_ldap_getAttr(result->entry, _EXEC_ID);
+ if (id == NULL || id[0] == NULL)
+ id_str = _NO_VALUE;
+ else
+ id_str = id[0];
+
+ attr = __ns_ldap_getAttr(result->entry, _EXEC_ATTRS);
+ if (attr == NULL || attr[0] == NULL)
+ attr_str = _NO_VALUE;
+ else
+ attr_str = attr[0];
+
+ /* 7 = 6 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(policy_str) + strlen(type_str) +
+ strlen(res1_str) + strlen(res2_str) + strlen(id_str) +
+ strlen(attr_str) + 7;
+
+ if (len > argp->buf.buflen) {
+ status = NSS_STR_PARSE_ERANGE;
+ goto result_exec2str;
}
-
-result_exec2ent:
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ status = NSS_STR_PARSE_PARSE;
+ goto result_exec2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s",
+ name[0], policy_str, type_str, res1_str,
+ res2_str, id_str, attr_str);
+ /* The front end marshaller does not need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(buffer);
+result_exec2str:
(void) __ns_ldap_freeResult(&be->result);
return (status);
}
@@ -300,10 +364,6 @@ _exec_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp)
ns_ldap_result_t *result = be->result;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getexecattr.c: _exec_process_val]\n");
-#endif /* DEBUG */
-
argp->returnval = NULL;
attrptr = getattr(result, 0);
if (attrptr == NULL) {
@@ -426,6 +486,54 @@ go_out:
}
static nss_status_t
+exec_attr_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp) {
+
+ _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
+ int stat, nss_stat = NSS_SUCCESS;
+
+ if (_priv_exec->search_flag == GET_ONE) {
+ /* ns_ldap_entry_t -> file format */
+ stat = (*be->ldapobj2str)(be, argp);
+
+ if (stat == NSS_STR_PARSE_SUCCESS) {
+ if (argp->buf.result != NULL) {
+ /* file format -> execstr_t */
+ stat = (*argp->str2ent)(be->buffer,
+ be->buflen,
+ argp->buf.result,
+ argp->buf.buffer,
+ argp->buf.buflen);
+ if (stat == NSS_STR_PARSE_SUCCESS) {
+ argp->returnval = argp->buf.result;
+ argp->returnlen = 1; /* irrelevant */
+ nss_stat = NSS_SUCCESS;
+ } else {
+ argp->returnval = NULL;
+ argp->returnlen = 0;
+ nss_stat = NSS_NOTFOUND;
+ }
+ } else {
+ /* return file format in argp->buf.buffer */
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ nss_stat = NSS_SUCCESS;
+ }
+ } else {
+ argp->returnval = NULL;
+ argp->returnlen = 0;
+ nss_stat = NSS_NOTFOUND;
+ }
+ } else {
+ /* GET_ALL */
+ nss_stat = _exec_process_val(be, argp);
+ _exec_cleanup(nss_stat, argp);
+ }
+
+ return (nss_stat);
+
+}
+
+static nss_status_t
getbynam(ldap_backend_ptr be, void *a)
{
char searchfilter[SEARCHFILTERLEN];
@@ -438,10 +546,6 @@ getbynam(ldap_backend_ptr be, void *a)
const char *policy = _priv_exec->policy;
const char *type = _priv_exec->type;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getexecattr.c: getbyname]\n");
-#endif /* DEBUG */
-
if (strpbrk(policy, "*()\\") != NULL ||
type != NULL && strpbrk(type, "*()\\") != NULL ||
_ldap_filter_name(name, _priv_exec->name, sizeof (name)) != 0)
@@ -458,31 +562,22 @@ getbynam(ldap_backend_ptr be, void *a)
nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR,
searchfilter, NULL, _merge_SSD_filter, userdata);
- if (nss_stat == NSS_SUCCESS)
- nss_stat = _exec_process_val(be, argp);
-
- _exec_cleanup(nss_stat, argp);
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = exec_attr_process_val(be, argp);
return (nss_stat);
}
-
static nss_status_t
getbyid(ldap_backend_ptr be, void *a)
{
- nss_status_t nss_stat;
+ nss_status_t nss_stat = NSS_SUCCESS;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getexecattr.c: getbyid]\n");
-#endif /* DEBUG */
-
nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID);
- if (nss_stat == NSS_SUCCESS)
- nss_stat = _exec_process_val(be, argp);
-
- _exec_cleanup(nss_stat, argp);
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = exec_attr_process_val(be, argp);
return (nss_stat);
}
@@ -494,16 +589,10 @@ getbynameid(ldap_backend_ptr be, void *a)
nss_status_t nss_stat;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getexecattr.c: getbynameid]\n");
-#endif /* DEBUG */
-
nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
- if (nss_stat == NSS_SUCCESS)
- nss_stat = _exec_process_val(be, argp);
-
- _exec_cleanup(nss_stat, argp);
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = exec_attr_process_val(be, argp);
return (nss_stat);
}
@@ -536,5 +625,5 @@ _nss_ldap_exec_attr_constr(const char *dummy1,
#endif
return ((nss_backend_t *)_nss_ldap_constr(execattr_ops,
sizeof (execattr_ops)/sizeof (execattr_ops[0]), _EXECATTR,
- exec_attrs, _nss_ldap_exec2ent));
+ exec_attrs, _nss_ldap_exec2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getgrent.c b/usr/src/lib/nsswitch/ldap/common/getgrent.c
index 1533ad8b3b..3456b6241f 100644
--- a/usr/src/lib/nsswitch/ldap/common/getgrent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -56,195 +55,106 @@ static const char *gr_attrs[] = {
/*
- * _nss_ldap_group2ent is the data marshaling method for the group getXbyY
+ * _nss_ldap_group2str is the data marshaling method for the group getXbyY
* (e.g., getgrnam(), getgrgid(), getgrent()) backend processes. This method
* is called after a successful ldap search has been performed. This method
- * will parse the ldap search values into struct group = argp->buf.buffer
- * which the frontend process expects. Three error conditions are expected
- * and returned to nsswitch.
+ * will parse the ldap search values into the file format.
+ * e.g.
+ *
+ * adm::4:root,adm,daemon
+ *
*/
static int
-_nss_ldap_group2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_group2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
+ int i;
int nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char **mp = NULL;
- char *val = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct group *grp = (struct group *)NULL;
+ int buflen = 0, len;
+ int firstime = 1;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
+ char **gname, **passwd, **gid, *password;
+ ns_ldap_attr_t *members;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- grp = (struct group *)argp->buf.result;
- ceiling = buffer + buflen;
- mp = grp->gr_mem = (char **)NULL;
-
- /* initialize no group password */
- grp->gr_passwd = (char *)NULL;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- if (strcasecmp(attrptr->attrname, _G_NAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- grp->gr_name = buffer;
- buffer += len + 1;
- if (buffer > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- (void) strcpy(grp->gr_name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _G_PASSWD) == 0) {
- val = attrptr->attrvalue[0];
- /*
- * Preen "{crypt}" if necessary.
- * If the password does not include the {crypt} prefix
- * then the password may be plain text. And thus
- * perhaps crypt(3c) should be used to encrypt it.
- * Currently the password is copied verbatim.
- */
- if (strncasecmp(val, _CRYPT,
- (sizeof (_CRYPT) - 1)) == 0)
- val += (sizeof (_CRYPT) - 1);
- len = strlen(val);
- grp->gr_passwd = buffer;
- buffer += len + 1;
- if (buffer > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- (void) strcpy(grp->gr_passwd, val);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _G_GID) == 0) {
- if (strlen(attrptr->attrvalue[0]) == 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- errno = 0;
- grp->gr_gid = (gid_t)strtol(attrptr->attrvalue[0],
- (char **)NULL, 10);
- if (errno != 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _G_MEM) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstime) {
- mp = grp->gr_mem =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)grp->gr_mem +
- sizeof (char *) *
- (attrptr->value_count + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer > ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- firstime = (int)0;
- }
- if (attrptr->attrvalue[j] == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_grp2ent;
- }
- len = strlen(attrptr->attrvalue[j]);
- if (len == 0)
- continue;
- *mp = buffer;
- buffer += len + 1;
- if (buffer > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- (void) strcpy(*mp++, attrptr->attrvalue[j]);
- continue;
- }
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = argp->buf.buflen;
+
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_grp2str;
}
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(buffer, 0, buflen);
+
+ gname = __ns_ldap_getAttr(result->entry, _G_NAME);
+ if (gname == NULL || gname[0] == NULL || (strlen(gname[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_grp2str;
}
- /* Don't leave password as null */
- if (grp->gr_passwd == (char *)NULL) {
+ passwd = __ns_ldap_getAttr(result->entry, _G_PASSWD);
+ if (passwd == NULL || passwd[0] == NULL || (strlen(passwd[0]) == 0)) {
+ /* group password could be NULL, replace it with "" */
+ password = _NO_PASSWD_VAL;
+ } else {
/*
- * The password may be missing; rfc2307bis defines
- * the 'posixGroup' attributes 'authPassword' and
- * 'userPassword' as being optional. Or a directory
- * access control may be preventing us from reading
- * the password. Currently we don't know which it is.
- * If it's an access problem then perhaps the password
- * should be set to "*NP*". But for now a simple empty
- * string is returned.
+ * Preen "{crypt}" if necessary.
+ * If the password does not include the {crypt} prefix
+ * then the password may be plain text. And thus
+ * perhaps crypt(3c) should be used to encrypt it.
+ * Currently the password is copied verbatim.
*/
- grp->gr_passwd = buffer;
- buffer += sizeof (_NO_PASSWD_VAL);
- if (buffer > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
- (void) strcpy(grp->gr_passwd, _NO_PASSWD_VAL);
+ if (strncasecmp(passwd[0], _CRYPT, strlen(_CRYPT)) == 0)
+ password = passwd[0] + strlen(_CRYPT);
+ else
+ password = passwd[0];
}
- if (mp == NULL) {
- mp = grp->gr_mem = (char **)ROUND_UP(buffer, sizeof (char **));
- buffer = (char *)grp->gr_mem + sizeof (char *);
- buffer = (char *)ROUND_UP(buffer, sizeof (char **));
- if (buffer > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_grp2ent;
- }
+ gid = __ns_ldap_getAttr(result->entry, _G_GID);
+ if (gid == NULL || gid[0] == NULL || (strlen(gid[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_grp2str;
}
- *mp = NULL;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getgrent.c: _nss_ldap_group2ent]\n");
- (void) fprintf(stdout, " gr_name: [%s]\n", grp->gr_name);
- if (grp->gr_passwd != (char *)NULL)
- (void) fprintf(stdout, " gr_passwd: [%s]\n",
- grp->gr_passwd);
- (void) fprintf(stdout, " gr_gid: [%ld]\n", grp->gr_gid);
- if (mp != NULL) {
- for (mp = grp->gr_mem; *mp != NULL; mp++)
- (void) fprintf(stdout, " gr_mem: [%s]\n", *mp);
+ len = snprintf(buffer, buflen, "%s:%s:%s:",
+ gname[0], password, gid[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_grp2str);
+
+ members = __ns_ldap_getAttrStruct(result->entry, _G_MEM);
+ if (members == NULL || members->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_grp2str;
}
-#endif /* DEBUG */
-
-result_grp2ent:
+ for (i = 0; i < members->value_count; i++) {
+ if (members->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_grp2str;
+ }
+ if (firstime) {
+ len = snprintf(buffer, buflen, "%s",
+ members->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_grp2str);
+ firstime = 0;
+ } else {
+ len = snprintf(buffer, buflen, ",%s",
+ members->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_grp2str);
+ }
+ }
+ /* The front end marshaller doesn't need the trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+result_grp2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
-
/*
* getbynam gets a group entry by name. This function constructs an ldap
* search filter using the name invocation parameter and the getgrnam search
@@ -262,9 +172,6 @@ getbynam(ldap_backend_ptr be, void *a)
char groupname[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getgrent.c: getbyname]\n");
-#endif /* DBEUG */
if (_ldap_filter_name(groupname, argp->key.name, sizeof (groupname))
!= 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -300,9 +207,6 @@ getbygid(ldap_backend_ptr be, void *a)
char userdata[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getgrent.c: getbygid]\n");
-#endif /* DBEUG */
ret = snprintf(searchfilter, sizeof (searchfilter),
_F_GETGRGID, (long)argp->key.uid);
if (ret >= sizeof (searchfilter) || ret < 0)
@@ -354,10 +258,7 @@ getbymember(ldap_backend_ptr be, void *a)
gid_t gid;
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getgrent.c: getbymember]\n");
-#endif /* DBEUG */
-
+ /* LINTED E_EXPR_NULL_EFFECT */
NSS_XbyY_ALLOC(&gb, sizeof (struct group), NSS_BUFLEN_GROUP);
NSS_XbyY_INIT(&argb, gb->result, gb->buffer, gb->buflen, 0);
@@ -414,7 +315,7 @@ getbymember(ldap_backend_ptr be, void *a)
curEntry = curEntry->next;
}
- __ns_ldap_freeResult((ns_ldap_result_t **)&be->result);
+ (void) __ns_ldap_freeResult((ns_ldap_result_t **)&be->result);
NSS_XbyY_FREE(&gb);
if (gcnt == argp->numgids)
return ((nss_status_t)NSS_NOTFOUND);
@@ -441,5 +342,5 @@ _nss_ldap_group_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(gr_ops,
sizeof (gr_ops)/sizeof (gr_ops[0]), _GROUP, gr_attrs,
- _nss_ldap_group2ent));
+ _nss_ldap_group2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/gethostent.c b/usr/src/lib/nsswitch/ldap/common/gethostent.c
index 78b84c785e..f327c232c6 100644
--- a/usr/src/lib/nsswitch/ldap/common/gethostent.c
+++ b/usr/src/lib/nsswitch/ldap/common/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -52,261 +51,203 @@ static const char *hosts_attrs[] = {
(char *)NULL
};
-
/*
- * _nss_ldap_hosts2ent is the data marshaling method for the hosts getXbyY
- * system call gethostbyname() and gethostbyaddr. The format of this call
- * is a cononical name and alias (alias is cononical name too) and one or
- * more IP addresses in support of multihomed hosts. This method is called
- * after a successful synchronous search has been performed. This method
- * will parse the search results into struct hostent = argp->buf.buffer
- * which gets returned to the frontend process. One of three error
- * conditions is also returned to nsswitch.
+ * _nss_ldap_hosts2str is the data marshaling method for the hosts getXbyY
+ * system call gethostbyname() and gethostbyaddr.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * 9.9.9.9 jurassic jurassic1 jurassic2
+ * 10.10.10.10 puppy
+ *
*/
-
-static int
-_nss_ldap_hosts2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+int
+_nss_ldap_hosts2str_int(int af, ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
+ uint_t i;
int nss_result;
- int buflen = (int)0;
- int firstimename = (int)1;
- int firstimedn = (int)1;
- int firstimeaddr = (int)1;
- unsigned long len = 0L;
- char **hn, **ha, **dp;
- char *cname = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct hostent *host = (struct hostent *)NULL;
- in_addr_t addr;
+ int buflen, buflen1, buflen2, len;
+ int firstimedn = 1, first_entry;
+ int validaddress = 0, copy_cname;
+ char *cname = NULL, *h_name = NULL;
+ char *buffer = NULL;
+ char *name;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
- in_addr_t inet_addr(const char *cp);
- int namecount = 0;
- int addrcount = 0;
- int aliascount = 0;
- int validaddress = 0;
- int gluelen = 0;
+ ns_ldap_attr_t *names;
ns_ldap_entry_t *entry;
- ns_ldap_attr_t *attr;
-#ifdef DEBUG
- struct in_addr in;
-#endif /* DEBUG */
-
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
+ char **ips = NULL, **dns = NULL;
+ char *first_host = NULL, *other_hosts = NULL;
+ char *buf1, *buf2;
+
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = buflen1 = buflen2 = argp->buf.buflen;
+
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+ if ((first_host = calloc(1, buflen1)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
}
-
- host = (struct hostent *)argp->buf.result;
- ceiling = buffer + buflen;
-
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
+ if ((other_hosts = calloc(1, buflen2)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
}
- namecount = 0;
- addrcount = 0;
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0, attr = entry->attr_pair[i];
- i < entry->attr_count; i++) {
- attr = entry->attr_pair[i];
- if (strcasecmp(attr->attrname, _H_NAME) == 0)
- namecount += attr->value_count;
- if (strcasecmp(attr->attrname, _H_ADDR) == 0)
- addrcount += attr->value_count;
- }
- }
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+ /*
+ * Multiple lines return will be sepereated by newlines
+ * Single line return or last line does not have newline
+ * e.g.
+ *
+ * 8.8.8.8 hostname
+ *
+ * or the search for hostname h1 returns 3 entries
+ *
+ * 9.9.9.9 h1
+ * 10.10.10.10 h1 xx
+ * 20.20.20.20 h1 yyy
+ *
+ * str2hostent expects all name/aliases in the first entry
+ * so the string is organized as
+ *
+ * "9.9.9.9 h1 xx yy\n10.10.10.10 \n20.20.20.20 "
+ *
+ * Use first_host to hold "9.9.9.9 h1 xx yy" and other_hosts to hold
+ * "\n10.10.10.10 \n20.20.20.20 "
+ *
+ */
+ buf1 = first_host;
+ buf2 = other_hosts;
+ first_entry = 1;
for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0; i < entry->attr_count; i++) {
- attrptr = entry->attr_pair[i];
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- if (strcasecmp(attrptr->attrname, _H_DN) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimedn) {
- /* get domain name associated with this dn */
- be->toglue = _get_domain_name(
- attrptr->attrvalue[j]);
- firstimedn = (int)0;
- }
- }
- }
- if (strcasecmp(attrptr->attrname, _H_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimename) {
- /* canonical name */
- cname = __s_api_get_canonical_name(result->entry,
- attrptr, 1);
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- if (be->toglue != NULL &&
- !DOTTEDSUBDOMAIN(cname))
- gluelen = strlen(be->toglue) + 1;
- else
- gluelen = 0;
- host->h_name = buffer;
- buffer += len + gluelen + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) strcpy(host->h_name, cname);
- if (gluelen > 0) {
- (void) strcat(host->h_name, ".");
- (void) strcat(host->h_name, be->toglue);
- }
- /* alias name */
- aliascount = (namecount >= 1 ? (namecount - 1) : 0);
- hn = host->h_aliases = (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)host->h_aliases +
- (sizeof (char *) * (aliascount + 1));
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- firstimename = (int)0;
- }
- /* alias list */
- if (aliascount > 0) {
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- /* skip canonical name */
- if (strcmp(cname, attrptr->attrvalue[j]) == 0)
- continue;
- /* check for duplicates */
- for (dp = host->h_aliases; *dp != NULL; dp++) {
- if (strcmp(*dp, attrptr->attrvalue[j]) == 0)
- goto next_alias;
- }
- if (be->toglue != NULL &&
- !DOTTEDSUBDOMAIN(attrptr->attrvalue[j]))
- gluelen = strlen(be->toglue) + 1;
- else
- gluelen = 0;
- *hn = buffer;
- buffer += len + gluelen + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) strcpy(*hn, attrptr->attrvalue[j]);
- if (gluelen > 0) {
- (void) strcat(*hn, ".");
- (void) strcat(*hn, be->toglue);
- }
- hn++;
- }
-next_alias:
- continue;
+ if (firstimedn) {
+ dns = __ns_ldap_getAttr(entry, _H_DN);
+ if (dns == NULL || dns[0] == NULL || strlen(dns[0]) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
}
- }
+ /* get domain name associated with this dn */
+ be->toglue = _get_domain_name(dns[0]);
+ firstimedn = 0;
}
- }
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0; i < entry->attr_count; i++) {
- attrptr = entry->attr_pair[i];
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- if (strcasecmp(attrptr->attrname, _H_ADDR) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimeaddr) {
- /* allocate 1 address per entry */
- ha = host->h_addr_list =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)host->h_addr_list +
- sizeof (char *) *
- (addrcount + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- firstimeaddr = (int)0;
- }
- /* filter out IPV6 addresses */
- addr = inet_addr(_strip_quotes(attrptr->attrvalue[j]));
- if (addr == (in_addr_t)-1) {
- goto next_addr;
- }
- validaddress++;
- /* check for duplicates */
- for (dp = host->h_addr_list; *dp != NULL; dp++) {
- if (memcmp(*dp, &addr, (size_t)sizeof (in_addr_t)) == 0)
- goto next_addr;
- }
- *ha = buffer;
- len = (unsigned long)sizeof (in_addr_t);
- buffer += len;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) memcpy(*ha++, (char *)&addr, (size_t)len);
-next_addr:
- continue;
- }
- }
+ /* Get IP */
+ ips = __ns_ldap_getAttr(entry, _H_ADDR);
+ if (ips == NULL || ips[0] == NULL || strlen(ips[0]) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
+ }
+ /* Skip IPV6 address in AF_INET mode */
+ if (af == AF_INET &&
+ (inet_addr(_strip_quotes(ips[0])) == (in_addr_t)-1))
+ continue;
+
+ /* A valid address for either af mode */
+ validaddress++;
+
+ if (first_entry) {
+ len = snprintf(buf1, buflen1, "%s", ips[0]);
+ TEST_AND_ADJUST(len, buf1, buflen1, result_host2str);
+ } else {
+ len = snprintf(buf2, buflen2, "\n%s ", ips[0]);
+ TEST_AND_ADJUST(len, buf2, buflen2, result_host2str);
}
- }
- if (validaddress == 0) {
- nss_result = (int)NSS_STR_PARSE_NO_ADDR;
- goto result_hosts2ent;
- }
+ /* Get host names */
+ names = __ns_ldap_getAttrStruct(entry, _H_NAME);
+ if (names == NULL || names->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
+ }
- host->h_addrtype = AF_INET;
- host->h_length = sizeof (uint_t);
+ /* Get canonical name of each entry */
+ cname = __s_api_get_canonical_name(entry,
+ names, 1);
+ if (cname == NULL || strlen(cname) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
+ }
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts2ent]\n");
- (void) fprintf(stdout, " h_name: [%s]\n", host->h_name);
- if (host->h_aliases != NULL) {
- for (hn = host->h_aliases; *hn != NULL; hn++)
- (void) fprintf(stdout, " h_aliases: [%s]\n", *hn);
- }
- (void) fprintf(stdout, " h_addrtype: [%d]\n", host->h_addrtype);
- (void) fprintf(stdout, " h_length: [%d]\n", host->h_length);
- for (ha = host->h_addr_list; *ha != NULL; ha++) {
- (void) memcpy(&in.s_addr, *ha, sizeof (in.s_addr));
- if (inet_ntoa(in) != NULL)
- (void) fprintf(stdout, " h_addr_list: [%s]\n",
- inet_ntoa(in));
+ /* Filter cname that's identical to h_name */
+ if (first_entry) {
+ h_name = cname;
+ first_entry = 0;
+ copy_cname = 1;
+ } else if (strcasecmp(cname, h_name) != 0) {
+ copy_cname = 1;
+ } else
+ copy_cname = 0;
+
+ if (copy_cname) {
+ /* Use the canonical name as the host name */
+ if (DOTTEDSUBDOMAIN(cname))
+ len = snprintf(buf1, buflen1, " %s", cname);
else
- (void) fprintf(stdout, " h_addr_list: <NULL>\n");
- }
-#endif /* DEBUG */
+ /* append domain name */
+ len = snprintf(buf1, buflen1, " %s.%s", cname,
+ be->toglue);
-result_hosts2ent:
+ TEST_AND_ADJUST(len, buf1, buflen1, result_host2str);
+ }
+
+ /* Append aliases */
+ for (i = 0; i < names->value_count; i++) {
+ name = names->attrvalue[i];
+ if (name == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_host2str;
+ }
+ /* Skip the canonical name and h_name */
+ if (strcasecmp(name, cname) != 0 &&
+ strcasecmp(name, h_name) != 0) {
+ if (DOTTEDSUBDOMAIN(name))
+ len = snprintf(buf1, buflen1, " %s", name);
+ else
+ /* append domain name */
+ len = snprintf(buf1, buflen1, " %s.%s",
+ name, be->toglue);
+ TEST_AND_ADJUST(len, buf1, buflen1, result_host2str);
+ }
+ }
+ }
+ if (validaddress == 0) {
+ /*
+ * For AF_INET mode, it found an IPv6 address and skipped it.
+ */
+ nss_result = NSS_STR_PARSE_NO_ADDR;
+ goto result_host2str;
+ }
+ /* Combine 2 strings */
+ len = snprintf(buffer, buflen, "%s%s", first_host, other_hosts);
+ TEST_AND_ADJUST(len, buffer, buflen, result_host2str);
+
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_host2str:
+ if (first_host)
+ free(first_host);
+ if (other_hosts)
+ free(other_hosts);
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
+static int
+_nss_ldap_hosts2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) {
+ return (_nss_ldap_hosts2str_int(AF_INET, be, argp));
+}
/*
* getbyname gets a struct hostent by hostname. This function constructs
@@ -484,10 +425,7 @@ _nss_ldap_hosts_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts_constr]\n");
-#endif /* DEBUG */
return ((nss_backend_t *)_nss_ldap_constr(hosts_ops,
sizeof (hosts_ops)/sizeof (hosts_ops[0]), _HOSTS,
- hosts_attrs, _nss_ldap_hosts2ent));
+ hosts_attrs, _nss_ldap_hosts2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/gethostent6.c b/usr/src/lib/nsswitch/ldap/common/gethostent6.c
index 8b0a453d69..1fad135afa 100644
--- a/usr/src/lib/nsswitch/ldap/common/gethostent6.c
+++ b/usr/src/lib/nsswitch/ldap/common/gethostent6.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,17 +19,17 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <netdb.h>
-#include <netinet/in.h>
+#include <sys/types.h>
#include <sys/socket.h>
-#include <inet/ip6.h>
-#include <syslog.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <sys/systeminfo.h>
#include "ns_internal.h"
#include "ldap_common.h"
@@ -57,254 +56,24 @@ static const char *ipnodes_attrs[] = {
(char *)NULL
};
-extern int inet_pton(int, const char *, void *);
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+extern int
+_nss_ldap_hosts2str_int(int af, ldap_backend_ptr be, nss_XbyY_args_t *argp);
/*
- * _nss_ldap_hosts2ent is the data marshaling method for the ipnodes getXbyY
- * system call gethostbyname() and gethostbyaddr. The format of this call
- * is a cononical name and alias (alias is cononical name too) and one or
- * more IP addresses in support of multihomed hosts. This method is called
- * after a successful synchronous search has been performed. This method
- * will parse the search results into struct hostent = argp->buf.buffer
- * which gets returned to the frontend process. One of three error
- * conditions is also returned to nsswitch.
+ * _nss_ldap_hosts2str is the data marshaling method for the ipnodes getXbyY
+ * system call gethostbyname() and gethostbyaddr.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * fe80::a00:20ff:fec4:f2b6 ipnodes_1
+ *
*/
-
static int
-_nss_ldap_hosts2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
-{
- int i, j;
- int nss_result;
- int buflen = (int)0;
- int firstimename = (int)1;
- int firstimedn = (int)1;
- int firstimeaddr = (int)1;
- unsigned long len = 0L;
- char **hn, **ha, **dp;
- char *cname = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct hostent *host = (struct hostent *)NULL;
- struct in6_addr addr6;
- struct in_addr addr;
- char *val;
- ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
- int namecount = 0;
- int addrcount = 0;
- int aliascount = 0;
- int gluelen = 0;
- ns_ldap_entry_t *entry;
- ns_ldap_attr_t *attr;
-
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- host = (struct hostent *)argp->buf.result;
- ceiling = buffer + buflen;
-
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
-
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0, attr = entry->attr_pair[i];
- i < entry->attr_count; i++) {
- attr = entry->attr_pair[i];
- if (strcasecmp(attr->attrname, _H_NAME) == 0)
- namecount += attr->value_count;
- if (strcasecmp(attr->attrname, _H_ADDR) == 0)
- addrcount += attr->value_count;
- }
- }
-
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0; i < entry->attr_count; i++) {
- attrptr = entry->attr_pair[i];
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- if (strcasecmp(attrptr->attrname, _H_DN) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimedn) {
- /* get domain name associated with this dn */
- be->toglue = _get_domain_name(
- attrptr->attrvalue[j]);
- firstimedn = (int)0;
- }
- }
- }
- if (strcasecmp(attrptr->attrname, _H_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimename) {
- /* canonical name */
- cname = __s_api_get_canonical_name(result->entry,
- attrptr, 1);
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- if (be->toglue != NULL &&
- !DOTTEDSUBDOMAIN(cname))
- gluelen = strlen(be->toglue) + 1;
- else
- gluelen = 0;
- host->h_name = buffer;
- buffer += len + gluelen + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) strcpy(host->h_name, cname);
- if (gluelen > 0) {
- (void) strcat(host->h_name, ".");
- (void) strcat(host->h_name, be->toglue);
- }
- /* alias name */
- aliascount = (namecount >= 1 ? (namecount - 1) : 0);
- hn = host->h_aliases =
- (char **)ROUND_UP(buffer, sizeof (char **));
- buffer = (char *)host->h_aliases +
- sizeof (char *) * (aliascount + 1);
- buffer = (char *)ROUND_UP(buffer, sizeof (char **));
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- firstimename = (int)0;
- }
- /* alias list */
- if (aliascount > 0) {
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
- /* skip canonical name */
- if (strcmp(attrptr->attrvalue[j], cname) == 0)
- continue;
- /* check for duplicates */
- for (dp = host->h_aliases; *dp != NULL; dp++) {
- if (strcmp(*dp, attrptr->attrvalue[j]) == 0)
- goto next_alias;
- }
- if (be->toglue != NULL &&
- !DOTTEDSUBDOMAIN(attrptr->attrvalue[j]))
- gluelen = strlen(be->toglue) + 1;
- else
- gluelen = 0;
- *hn = buffer;
- buffer += len + gluelen + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) strcpy(*hn, attrptr->attrvalue[j]);
- if (gluelen > 0) {
- (void) strcat(*hn, ".");
- (void) strcat(*hn, be->toglue);
- }
- hn++;
- }
-next_alias:
- continue;
- }
- }
- }
- }
-
- for (entry = result->entry; entry != NULL; entry = entry->next) {
- for (i = 0; i < entry->attr_count; i++) {
- attrptr = entry->attr_pair[i];
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_hosts2ent;
- }
-
- if (strcasecmp(attrptr->attrname, _H_ADDR) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstimeaddr) {
- /* allocate 1 address per entry */
- ha = host->h_addr_list = (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)host->h_addr_list +
- sizeof (char *) * (addrcount + 1);
- buffer = (char *)ROUND_UP(buffer, sizeof (char **));
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- firstimeaddr = (int)0;
- }
- val = (char *)_strip_quotes(attrptr->attrvalue[j]);
- if (inet_pton(AF_INET6, val, (void *) &addr6) != 1) {
- if (inet_pton(AF_INET, val, (void *) &addr) != 1) {
- goto next_addr;
- } else {
- IN6_INADDR_TO_V4MAPPED(&addr, &addr6);
- }
- }
-
- /* check for duplicates */
- for (dp = host->h_addr_list; *dp != NULL; dp++) {
- if (memcmp(*dp, &addr6, sizeof (struct in6_addr))
- == 0)
- goto next_addr;
- }
- *ha = buffer;
- len = (unsigned long)sizeof (struct in6_addr);
- buffer += len;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_hosts2ent;
- }
- (void) memcpy(*ha++, (char *)&addr6, (size_t)len);
-next_addr:
- continue;
- }
- }
- }
- }
-
- host->h_addrtype = AF_INET6;
- host->h_length = IPV6_ADDR_LEN;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_byname2ent]\n");
- (void) fprintf(stdout, " h_name: [%s]\n", host->h_name);
- if (host->h_aliases != NULL) {
- for (hn = host->h_aliases; *hn != NULL; hn++)
- (void) fprintf(stdout, " h_aliases: [%s]\n", *hn);
- }
- (void) fprintf(stdout, " h_addrtype: [%d]\n", host->h_addrtype);
- (void) fprintf(stdout, " h_length: [%d]\n", host->h_length);
-
- for (hn = host->h_addr_list; *hn != NULL; hn++) {
- char addrbuf[INET6_ADDRSTRLEN + 1];
- (void) fprintf(stdout, " haddr_list: [%s]\n",
- inet_ntop(AF_INET6, (void *)hn, (void *)addrbuf,
- INET6_ADDRSTRLEN));
- }
-#endif /* DEBUG */
-
-result_hosts2ent:
-
- (void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+_nss_ldap_hosts2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) {
+ return (_nss_ldap_hosts2str_int(AF_INET6, be, argp));
}
-
/*
* getbyname gets a struct hostent by hostname. This function constructs
* an ldap search filter using the name invocation parameter and the
@@ -325,10 +94,6 @@ getbyname(ldap_backend_ptr be, void *a)
char userdata[SEARCHFILTERLEN];
int rc;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent6.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(hostname, argp->key.ipnode.name,
sizeof (hostname)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -432,9 +197,6 @@ getbyaddr(ldap_backend_ptr be, void *a)
char userdata[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent6.c: getbyaddr]\n");
-#endif /* DEBUG */
argp->h_errno = 0;
if ((argp->key.hostaddr.type != AF_INET6) ||
(argp->key.hostaddr.len != sizeof (addr)))
@@ -493,10 +255,7 @@ _nss_ldap_ipnodes_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[gethostent6.c: _nss_ldap_host6_constr]\n");
-#endif /* DEBUG */
return ((nss_backend_t *)_nss_ldap_constr(ipnodes_ops,
sizeof (ipnodes_ops)/sizeof (ipnodes_ops[0]), _HOSTS6,
- ipnodes_attrs, _nss_ldap_hosts2ent));
+ ipnodes_attrs, _nss_ldap_hosts2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getkeyent.c b/usr/src/lib/nsswitch/ldap/common/getkeyent.c
index c1c9dbd381..95f27cddb9 100644
--- a/usr/src/lib/nsswitch/ldap/common/getkeyent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getkeyent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -49,69 +48,58 @@ static const char *keys_attrs[] = {
/*
- * _nss_ldap_key2ent is the data marshaling method for the publickey getXbyY
+ * _nss_ldap_key2str is the data marshaling method for the publickey getXbyY
* (e.g., getpublickey() and getsecretkey()) backend processes. This method
* is called after a successful ldap search has been performed. This method
- * will parse the ldap search values into "public:secret" key string =
- * argp->buf.buffer which the frontend process expects. Three error
- * conditions are expected and returned to nsswitch.
+ * will parse the ldap search values into "public:secret" file format.
+ *
+ * c3d91f44568fbbefada50d336d9bd67b16e7016f987bb607:
+ * 7675cd9b8753b5db09dabf12da759c2bd1331c927bb322861fffb54be13f55e9
+ *
+ * (All in one line)
+ *
+ * Publickey does not have a front end marshaller so db_type is set
+ * for special handling.
*/
static int
-_nss_ldap_key2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_key2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
int nss_result;
char *keytype = (char *)argp->key.pkey.keytype;
int keytypelen = strlen(keytype);
- char *key_start = NULL;
- int key_len;
- int buflen = (size_t)argp->buf.buflen;
- char *buffer = (char *)argp->buf.buffer;
- char *ceiling = (char *)NULL;
+ int len;
+ int buflen = argp->buf.buflen;
+ char *buffer, *pkey, *skey;
ns_ldap_result_t *result = be->result;
- char **key_array;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpublikey.c: _nss_ldap_passwd2ent]\n");
-#endif /* DEBUG */
+ char **pkey_array, **skey_array;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_key2ent;
+ if (result == NULL || keytype == NULL) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_key2str;
}
- ceiling = buffer + buflen;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(buffer, 0, buflen);
-
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
/* get the publickey */
- key_array = __ns_ldap_getAttr(result->entry, _KEY_NISPUBLICKEY);
- if (key_array == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_key2ent;
+ pkey_array = __ns_ldap_getAttr(result->entry, _KEY_NISPUBLICKEY);
+ if (pkey_array == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_key2str;
}
- while (*key_array) {
- if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
+ while (*pkey_array) {
+ if (strncasecmp(*pkey_array, keytype, keytypelen) == NULL)
break;
- key_array++;
- }
- if (*key_array == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_key2ent;
+ pkey_array++;
}
-
- key_start = *(key_array) + keytypelen;
- key_len = strlen(key_start) + 1;
- if (buffer + key_len + 2 > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_key2ent;
+ if (*pkey_array == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_key2str;
}
- (void) strncpy(buffer, key_start, key_len);
- (void) strcat(buffer, ":");
- buffer += strlen(buffer);
+ pkey = *pkey_array + keytypelen;
/* get the secretkey */
- key_array = __ns_ldap_getAttr(result->entry, _KEY_NISSECRETKEY);
- if (key_array == NULL) {
+ skey_array = __ns_ldap_getAttr(result->entry, _KEY_NISSECRETKEY);
+ if (skey_array == NULL) {
/*
* if we got this far, it's possible that the secret
* key is actually missing or no permission to read it.
@@ -120,33 +108,37 @@ _nss_ldap_key2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
* the only possibility of reaching this here is due to
* missing secret key.
*/
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_key2ent;
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_key2str;
}
- while (*key_array) {
- if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
+ while (*skey_array) {
+ if (strncasecmp(*skey_array, keytype, keytypelen) == NULL)
break;
- key_array++;
+ skey_array++;
}
- if (*key_array == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_key2ent;
+ if (*skey_array == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_key2str;
}
+ skey = *skey_array + keytypelen;
- key_start = *(key_array) + keytypelen;
- key_len = strlen(key_start);
- if (buffer + key_len + 1 > ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_key2ent;
+ /* 2 = 1 ':' + 1 '\0' */
+ len = strlen(pkey) + strlen(skey) + 2;
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_key2str;
}
- (void) strcat(buffer, key_start);
+ /*
+ * publickey does not have a frontend marshaller.
+ * copy the result to buf.buffer directly
+ */
+ buffer = argp->buf.buffer;
+
+ (void) snprintf(buffer, len, "%s:%s", pkey, skey);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_key2ent]\n");
- (void) fprintf(stdout, "\treturn: %s\n", buffer);
-#endif /* DEBUG */
+ be->db_type = NSS_LDAP_DB_PUBLICKEY;
-result_key2ent:
+result_key2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
@@ -176,10 +168,6 @@ getkeys(ldap_backend_ptr be, void *a)
nss_status_t rc;
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n");
-#endif /* DEBUG */
-
/*
* We need to break it down to find if this is a netname for host
* or user. We'll pass the domain as is to the LDAP call.
@@ -187,6 +175,7 @@ getkeys(ldap_backend_ptr be, void *a)
if (_ldap_filter_name(netname, argp->key.pkey.name, sizeof (netname))
!= 0)
return ((nss_status_t)NSS_NOTFOUND);
+
domain = strchr(netname, '@');
if (!domain)
return ((nss_status_t)NSS_NOTFOUND);
@@ -252,11 +241,7 @@ _nss_ldap_publickey_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_keys_constr]\n");
-#endif /* DEBUG */
-
return ((nss_backend_t *)_nss_ldap_constr(keys_ops,
sizeof (keys_ops)/sizeof (keys_ops[0]),
- _PUBLICKEY, keys_attrs, _nss_ldap_key2ent));
+ _PUBLICKEY, keys_attrs, _nss_ldap_key2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetent.c b/usr/src/lib/nsswitch/ldap/common/getnetent.c
index a5afb360ce..d042e0fe2b 100644
--- a/usr/src/lib/nsswitch/ldap/common/getnetent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getnetent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,8 +37,10 @@
#define _N_NETWORK "ipnetworknumber"
#define _F_GETNETBYNAME "(&(objectClass=ipNetwork)(cn=%s))"
#define _F_GETNETBYNAME_SSD "(&(%%s)(cn=%s))"
-#define _F_GETNETBYADDR "(&(objectClass=ipNetwork)(ipNetworkNumber=%s))"
-#define _F_GETNETBYADDR_SSD "(&(%%s)(ipNetworkNumber=%s))"
+#define _F_GETNETBYADDR "(&(objectClass=ipNetwork)(|(ipNetworkNumber=%s)" \
+ "(ipNetworkNumber=%s)))"
+#define _F_GETNETBYADDR_SSD "(&(%%s)(|(ipNetworkNumber=%s)" \
+ "(ipNetworkNumber=%s)))"
static const char *networks_attrs[] = {
_N_NAME,
@@ -48,187 +49,119 @@ static const char *networks_attrs[] = {
};
/*
- * _nss_ldap_networks2ent is the data marshaling method for the networks
+ * _nss_ldap_networks2str is the data marshaling method for the networks
* getXbyY * (e.g., getbyname(), getbyaddr(), getnetent() backend processes.
* This method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into struct netent =
- * argp->buf.buffer which the frontend process expects. Three error conditions
- * are expected and returned to nsswitch.
+ * This method will parse the ldap search values into the file format.
+ * e.g.
+ *
+ * SunRay-ce2 10.34.96.0 SunRay
+ *
*/
-
static int
-_nss_ldap_networks2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_networks2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
+ uint_t i;
int nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char **mp, *cname = NULL;
-#ifdef DEBUG
- char addrstr[16];
-#endif /* DEBUG */
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct netent *ntk = (struct netent *)NULL;
+ int buflen = 0, len;
+ char **network, *cname = NULL;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
+ ns_ldap_attr_t *names;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_net2ent;
- }
- ntk = (struct netent *)argp->buf.result;
- ceiling = buffer + buflen;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = argp->buf.buflen;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_net2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_net2ent;
+ names = __ns_ldap_getAttrStruct(result->entry, _N_NAME);
+ if (names == NULL || names->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_net2str;
}
-
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_net2ent;
- }
- if (strcasecmp(attrptr->attrname, _N_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstime) {
- /*
- * The definition of the object class
- * "ipNetwork" has a descripency between
- * RFC 2307 and 2307bis.
- * In 2307, "cn" is a MUST attribute.
- * In 2307bis, "cn" is a MAY attribute.
- * If "cn" is a MAY attribute,
- * it does not appear in RDN and can't
- * be derived from RDN as a canonical
- * "cn" name. In that case, use 1st
- * "cn" value as the official name.
- */
- cname = __s_api_get_canonical_name(
- result->entry, attrptr, 1);
- if (cname == NULL)
- /* 2307bis case */
- cname = attrptr->attrvalue[j];
-
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result =
- NSS_STR_PARSE_PARSE;
- goto result_net2ent;
- }
- ntk->n_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_net2ent;
- }
- (void) strcpy(ntk->n_name, cname);
- /* alias list */
- mp = ntk->n_aliases =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)ntk->n_aliases +
- sizeof (char *) *
- (attrptr->value_count + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_net2ent;
- }
- firstime = (int)0;
- }
- /* alias list */
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_net2ent;
- }
- /* skip canonical name(official name) */
- if (strcmp(attrptr->attrvalue[j], cname) == 0)
- continue;
- *mp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_net2ent;
- }
- (void) strcpy(*mp++, attrptr->attrvalue[j]);
- continue;
- }
+ /* Get the canonical name */
+ cname = __s_api_get_canonical_name(result->entry, names, 1);
+ /*
+ * The definition of the object class "ipNetwork" has a
+ * discrepency between RFC 2307 and 2307bis.
+ * In 2307, "cn" is a MUST attribute. In 2307bis, "cn" is a
+ * MAY attribute.
+ * If "cn" is a MAY attribute, it does not appear in RDN and can't
+ * be derived from RDN as a canonical "cn" name. In that case, use 1st
+ * "cn" value as the official name.
+ */
+ if (cname == NULL)
+ /* 2307bis case */
+ cname = names->attrvalue[0];
+ if (cname == NULL || (len = strlen(cname)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_net2str;
+ }
+ network = __ns_ldap_getAttr(result->entry, _N_NETWORK);
+ if (network == NULL || network[0] == NULL ||
+ (len = strlen(network[0])) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_net2str;
+ }
+ len = snprintf(buffer, buflen, "%s %s", cname, network[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_net2str);
+ /* Append aliases */
+ for (i = 0; i < names->value_count; i++) {
+ if (names->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_net2str;
}
- if (strcasecmp(attrptr->attrname, _N_NETWORK) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_net2ent;
- }
- if ((ntk->n_net = (in_addr_t)
- inet_network(attrptr->attrvalue[0])) ==
- (in_addr_t)-1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_net2ent;
- }
-#ifdef DEBUG
- strlcpy(addrstr, attrptr->attrvalue[0],
- sizeof (addrstr));
-#endif /* DEBUG */
- continue;
+ /* Skip the canonical name */
+ if (strcasecmp(names->attrvalue[i], cname) != 0) {
+ len = snprintf(buffer, buflen, " %s",
+ names->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_net2str);
}
}
- ntk->n_addrtype = AF_INET;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getnetent.c: _nss_ldap_networks2ent]\n");
- (void) fprintf(stdout, " n_name: [%s]\n", ntk->n_name);
- if (mp != NULL) {
- for (mp = ntk->n_aliases; *mp != NULL; mp++)
- (void) fprintf(stdout, " n_aliases: [%s]\n", *mp);
- }
- if (ntk->n_addrtype == AF_INET)
- (void) fprintf(stdout, " n_addrtype: [AF_INET]\n");
- else
- (void) fprintf(stdout, " n_addrtype: [%d]\n",
- ntk->n_addrtype);
- (void) fprintf(stdout, " n_net: [%s]\n", addrstr);
-#endif /* DEBUG */
-result_net2ent:
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_net2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
-
/*
* Takes an unsigned integer in host order, and returns a printable
* string for it as a network number. To allow for the possibility of
* naming subnets, only trailing dot-zeros are truncated.
+ * buf2 is untruncated version.
*/
-static int nettoa(int anet, char *buf, int buflen)
+static int nettoa(int anet, char *buf, char *buf2, int buflen)
{
int addr;
char *p;
struct in_addr in;
- if (buf == 0)
+ if (buf == NULL || buf2 == NULL)
return ((int)1);
in = inet_makeaddr(anet, INADDR_ANY);
addr = in.s_addr;
- if (strlcpy(buf, inet_ntoa(in), buflen) >= buflen)
+ if (inet_ntop(AF_INET, (const void *)&in, buf2, INET_ADDRSTRLEN)
+ == NULL)
+ return ((int)1);
+ if (strlcpy(buf, buf2, buflen) >= buflen)
return ((int)1);
if ((IN_CLASSA_HOST & htonl(addr)) == 0) {
p = strchr(buf, '.');
@@ -304,21 +237,22 @@ static nss_status_t
getbyaddr(ldap_backend_ptr be, void *a)
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- char addrstr[16];
+ char addrstr[INET_ADDRSTRLEN], addrstr2[INET_ADDRSTRLEN];
char searchfilter[SEARCHFILTERLEN];
char userdata[SEARCHFILTERLEN];
int ret;
- if (nettoa((int)argp->key.netaddr.net, addrstr, 16) != 0)
+ if (nettoa((int)argp->key.netaddr.net, addrstr, addrstr2,
+ INET_ADDRSTRLEN) != 0)
return ((nss_status_t)NSS_UNAVAIL);
ret = snprintf(searchfilter, sizeof (searchfilter),
- _F_GETNETBYADDR, addrstr);
+ _F_GETNETBYADDR, addrstr, addrstr2);
if (ret >= sizeof (searchfilter) || ret < 0)
return ((nss_status_t)NSS_NOTFOUND);
ret = snprintf(userdata, sizeof (userdata),
- _F_GETNETBYADDR_SSD, addrstr);
+ _F_GETNETBYADDR_SSD, addrstr, addrstr2);
if (ret >= sizeof (userdata) || ret < 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -351,5 +285,5 @@ _nss_ldap_networks_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(net_ops,
sizeof (net_ops)/sizeof (net_ops[0]), _NETWORKS,
- networks_attrs, _nss_ldap_networks2ent));
+ networks_attrs, _nss_ldap_networks2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetgrent.c b/usr/src/lib/nsswitch/ldap/common/getnetgrent.c
index 01728e3420..d3072440f2 100644
--- a/usr/src/lib/nsswitch/ldap/common/getnetgrent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getnetgrent.c
@@ -890,7 +890,7 @@ netgr_set(ldap_backend_ptr be, void *a)
get_be->tablename = NULL;
get_be->attrs = netgrent_attrs;
get_be->result = NULL;
- get_be->ldapobj2ent = NULL;
+ get_be->ldapobj2str = NULL;
get_be->setcalled = 1;
get_be->filter = NULL;
get_be->toglue = NULL;
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetmasks.c b/usr/src/lib/nsswitch/ldap/common/getnetmasks.c
index 69ef802520..2e6f28053e 100644
--- a/usr/src/lib/nsswitch/ldap/common/getnetmasks.c
+++ b/usr/src/lib/nsswitch/ldap/common/getnetmasks.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,80 +46,61 @@ static const char *netmasks_attrs[] = {
/*
- * _nss_ldap_netmasks2ent is the data marshaling method for the netmasks
- * getXbyY * (e.g., getbynet()) backend processes. This method is called
- * after a successful ldap search has been performed. This method will
- * parse the ldap search values into struct in_addr *mask = argp->buf.result
- * only if argp->buf.result is initialized (not NULL). Three error
- * conditions are expected and returned to nsswitch.
+ * _nss_ldap_netmasks2str is the data marshaling method for the netmasks
+ * getXbyY * (e.g., getnetmaskby[net|addr]()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into the file format.
+ *
+ * getnetmaskbykey set argp->buf.buffer to NULL and argp->buf.buflen to 0
+ * and argp->buf.result to non-NULL.
+ * The front end marshaller str2add expects "netmask" only
+ *
+ * e.g.
+ *
+ * 255.255.255.0
+ *
+ *
*/
static int
-_nss_ldap_netmasks2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_netmasks2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
- int nss_result;
- unsigned long len = 0L;
-#ifdef DEBUG
- char maskstr[16];
-#endif /* DEBUG */
- struct in_addr addr;
- struct in_addr *mask = (struct in_addr *)NULL;
+ int nss_result, len;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
+ char *buffer, **netmask;
- mask = (struct in_addr *)argp->buf.result;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_nmks2ent;
- }
+ nss_result = NSS_STR_PARSE_SUCCESS;
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_nmks2ent;
- }
- if (strcasecmp(attrptr->attrname, _N_NETMASK) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (mask == NULL)
- continue;
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_nmks2ent;
- }
- /* addr a IPv4 address and 32 bits */
- addr.s_addr = inet_addr(attrptr->attrvalue[j]);
- if (addr.s_addr == 0xffffffffUL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_nmks2ent;
- }
- mask->s_addr = addr.s_addr;
-#ifdef DEBUG
- strlcpy(maskstr, attrptr->attrvalue[j],
- sizeof (maskstr));
-#endif /* DEBUG */
- continue;
- }
- }
+ netmask = __ns_ldap_getAttr(result->entry, _N_NETMASK);
+ if (netmask == NULL || netmask[0] == NULL ||
+ (strlen(netmask[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_nmks2str;
}
+ /* Add a trailing null for debugging purpose */
+ len = strlen(netmask[0]) + 1;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_nmks2str;
+ }
+ be->buflen = len - 1;
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[netmasks.c: _nss_ldap_netmasks2ent]\n");
- (void) fprintf(stdout, " netmask: [%s]\n", maskstr);
-#endif /* DEBUG */
-result_nmks2ent:
+ (void) snprintf(buffer, len, "%s", netmask[0]);
+
+result_nmks2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
-
/*
* getbynet gets a network mask by address. This function constructs an
* ldap search filter using the netmask name invocation parameter and the
@@ -142,7 +122,6 @@ getbynet(ldap_backend_ptr be, void *a)
if (_ldap_filter_name(netnumber, argp->key.name, sizeof (netnumber))
!= 0)
return ((nss_status_t)NSS_NOTFOUND);
-
ret = snprintf(searchfilter, sizeof (searchfilter),
_F_GETMASKBYNET, netnumber);
if (ret >= sizeof (searchfilter) || ret < 0)
@@ -179,5 +158,5 @@ _nss_ldap_netmasks_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(netmasks_ops,
sizeof (netmasks_ops)/sizeof (netmasks_ops[0]), _NETMASKS,
- netmasks_attrs, _nss_ldap_netmasks2ent));
+ netmasks_attrs, _nss_ldap_netmasks2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprinter.c b/usr/src/lib/nsswitch/ldap/common/getprinter.c
index f4004be41a..aae2f326cb 100644
--- a/usr/src/lib/nsswitch/ldap/common/getprinter.c
+++ b/usr/src/lib/nsswitch/ldap/common/getprinter.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,6 +35,9 @@ static void append_attr(char *buf, char *attr);
#define _F_GETPRINTERBYNAME \
"(&(objectClass=sunPrinter)(|(printer-name=%s)(printer-aliases=%s)))"
+#define PRINTER_PREFIX "printer-"
+#define SUNWPR_PREFIX "sunwpr-"
+
/*
* Attributes from the following classes:
* printerService
@@ -50,85 +52,82 @@ static const char **printer_attrs = NULL;
/*
- * _nss_ldap_printers2ent is the data marshaling method for the printers
+ * _nss_ldap_printers2str is the data marshaling method for the printers
* getXbyY backend processes. This method is called after a successful
* ldap search has been performed. This method will parse the ldap search
* values into argp->buf.buffer. Three error conditions are expected and
* returned to nsswitch.
+ * In order to be compatible with old data output, the code is commented out
+ * with NSS_LDAP_PRINTERS. The NSS_LDAP_PRINTERS section is for future
+ * refrences if it's decided to fix the output format.
*/
static int
-_nss_ldap_printers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_printers2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
int i, j;
int nss_result;
- int buflen = (int)0;
- unsigned long len = 0L;
- char *cp = (char *)NULL;
- char *buffer = (char *)NULL;
+ int buflen = 0, len;
+ char *buffer = NULL;
+ char **name, *attrname;
ns_ldap_attr_t *attr;
ns_ldap_result_t *result = be->result;
+#ifdef NSS_LDAP_PRINTERS
+ int slen, plen;
+#endif
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_printers2ent;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+
+ buflen = argp->buf.buflen;
+ if (argp->buf.result != NULL) {
+ be->buffer = calloc(1, buflen);
+ if (be->buffer == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = buflen;
+ buffer = be->buffer;
+ } else {
+ buffer = argp->buf.buffer;
+ (void) memset(argp->buf.buffer, 0, buflen);
}
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
-
- /* Make sure our buffer stays NULL terminated */
- buflen--;
+ nss_result = NSS_STR_PARSE_SUCCESS;
- attr = getattr(result, 0);
- if (attr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
- }
+#ifdef NSS_LDAP_PRINTERS
+ slen = strlen(SUNWPR_PREFIX);
+ plen = strlen(PRINTER_PREFIX);
+#endif
/*
- * Pick out the printer name.
+ * Pick out the printer name and aliases
*/
- for (i = 0; i < result->entry->attr_count; i++) {
- attr = getattr(result, i);
- if (attr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
- }
- if (strcasecmp(attr->attrname, "printer-name") == 0) {
- len = strlen(attr->attrvalue[0]);
- if (len < 1 || (attr->attrvalue[0] == '\0')) {
- *buffer = 0;
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
- }
- if (len > buflen) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_printers2ent;
- }
- (void) strcpy(buffer, attr->attrvalue[0]);
- }
+ name = __ns_ldap_getAttr(result->entry, "printer-name");
+ if (name == NULL || name[0] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_printers2str;
}
-
- /*
- * Should never happen since it is mandatory but bail if
- * we don't have a printer name.
- */
- if (buffer[0] == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
+ len = snprintf(buffer, buflen, "%s", name[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_printers2str);
+
+#ifdef NSS_LDAP_PRINTERS
+ attr = __ns_ldap_getAttrStruct(result->entry, "printer-aliases");
+ if (attr != NULL && attr->attrvalue != NULL) {
+ for (i = 0; i < attr->value_count; i++) {
+ len = snprintf(buffer, buflen, "|%s",
+ attr->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen,
+ result_printers2str);
+ }
}
-
+#endif
/*
* Add the rest of the attributes
*/
for (i = 0; i < result->entry->attr_count; i++) {
attr = getattr(result, i);
if (attr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_printers2str;
}
/*
* The attribute contains key=value
@@ -140,51 +139,76 @@ _nss_ldap_printers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
(attr->attrvalue[j] == '\0')) {
*buffer = 0;
nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
- }
- len += strlen(buffer) + 1; /* 1 for ':' */
- if (len > buflen) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_printers2ent;
- }
- if ((cp = strrchr(buffer, '\0')) != NULL) {
- *cp = ':';
- (void) strcat(buffer,
- attr->attrvalue[j]);
+ goto result_printers2str;
}
+ len = snprintf(buffer, buflen, ":%s",
+ attr->attrvalue[j]);
+ TEST_AND_ADJUST(len, buffer, buflen,
+ result_printers2str);
}
} else {
/*
- * Skip the printer name
+ * Skip some attr names
*/
- if (strcmp(attr->attrname, "printer-name") == 0) {
+#ifdef NSS_LDAP_PRINTERS
+ if (strcasecmp(attr->attrname, "printer-name") == 0 ||
+ strcasecmp(attr->attrname, "dn") == 0 ||
+ strcasecmp(attr->attrname,
+ "objectclass") == 0 ||
+ strcasecmp(attr->attrname,
+ "printer-uri") == 0 ||
+ strcasecmp(attr->attrname,
+ "printer-aliases") == 0)
+#else
+ if (strcasecmp(attr->attrname, "printer-name") == 0)
+#endif
continue;
}
/*
- * Translate sun-printer-bsdaddr -> bsdaddr
+ * Translate attr name ->key name
*/
- if (strcmp(attr->attrname, "sun-printer-bsdaddr") ==
- 0) {
- if (attr->attrname != NULL) {
- free(attr->attrname);
- }
- attr->attrname = strdup("bsdaddr");
- }
+ if (strcmp(attr->attrname, "sun-printer-bsdaddr")
+ == 0)
+ attrname = "bsdaddr";
+#ifdef NSS_LDAP_PRINTERS
+ else if (strcmp(attr->attrname, "printer-info")
+ == 0)
+ attrname = "description";
+ else if (strcmp(attr->attrname, "sunwpr-support")
+ == 0)
+ attrname = "itopssupported";
+ else if (strncmp(attr->attrname, PRINTER_PREFIX, plen)
+ == 0)
+ attrname = attr->attrname + plen;
+ else if (strncmp(attr->attrname, SUNWPR_PREFIX, slen)
+ == 0)
+ attrname = attr->attrname + slen;
+#endif
+ else
+ attrname = attr->attrname;
/*
- * The attribute name is the key. The attribute
+ * The attrname is the key. The attribute
* data is the value.
*/
+ len = snprintf(buffer, buflen, ":%s=", attrname);
+ TEST_AND_ADJUST(len, buffer, buflen,
+ result_printers2str);
+
for (j = 0; j < attr->value_count; j++) {
int k;
char *kp;
+ if (attr->attrvalue[j] == NULL) {
+ *buffer = 0;
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_printers2str;
+ }
len = strlen(attr->attrvalue[j]);
- if (len < 1 ||
- (attr->attrvalue[j] == '\0')) {
+ if (len < 1) {
*buffer = 0;
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_printers2ent;
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_printers2str;
}
/*
* Add extra for any colons which need to
@@ -193,38 +217,33 @@ _nss_ldap_printers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
k = 0;
for (kp = attr->attrvalue[j]; *kp != NULL; kp++)
if (*kp == ':')
+ /* count ':' in value */
k++;
- len += strlen(buffer) + k;
+ if (j == 0)
+ /* first time */
+ len += k;
+ else
+ /* add ',' */
+ len += k + 1;
- if (j == 0) {
- len += strlen(attr->attrname) + 1;
- }
if (len > buflen) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_printers2ent;
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_printers2str;
}
- if ((cp = strrchr(buffer, '\0')) != NULL) {
- if (j == 0) {
- *cp = ':';
- (void) strcat(buffer,
- attr->attrname);
- (void) strcat(buffer, "=");
- } else {
- *cp = ',';
- }
- (void) append_attr(buffer,
+ if (j > 0)
+ *buffer++ = ',';
+
+ (void) append_attr(buffer,
attr->attrvalue[j]);
- }
+ buffer += strlen(attr->attrvalue[j]) + k;
+ buflen -= len;
}
- }
}
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getprinter.c: _nss_ldap_printers2ent]\n");
- (void) fprintf(stdout, " printers: [%s]\n", buffer);
-#endif
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
-result_printers2ent:
+result_printers2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
@@ -241,7 +260,7 @@ append_attr(char *buf, char *attr)
(void) strcat(buf, attr);
return;
}
- bp = buf + strlen(buf);
+ bp = buf;
cp = attr;
while (*cp != NULL) {
if (*cp == ':') {
@@ -257,7 +276,7 @@ append_attr(char *buf, char *attr)
* parameter and the getprinterbyname search filter defined. Once the
* filter is constructed, we search for matching entries and marshal
* the data results into argp->buf.buffer for the frontend process.
- * The function * _nss_ldap_printers2ent performs the data marshaling.
+ * The function _nss_ldap_printers2str performs the data marshaling.
*/
static nss_status_t
@@ -297,12 +316,7 @@ _nss_ldap_printers_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[getprinterent.c: _nss_ldap_printers_constr]\n");
-#endif
-
return ((nss_backend_t *)_nss_ldap_constr(printers_ops,
sizeof (printers_ops)/sizeof (printers_ops[0]), _PRINTERS,
- printer_attrs, _nss_ldap_printers2ent));
+ printer_attrs, _nss_ldap_printers2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprofattr.c b/usr/src/lib/nsswitch/ldap/common/getprofattr.c
index d4c4adf6d4..dc8469ce58 100644
--- a/usr/src/lib/nsswitch/ldap/common/getprofattr.c
+++ b/usr/src/lib/nsswitch/ldap/common/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,7 +36,9 @@
#define _PROF_RES2 "SolarisAttrReserved2"
#define _PROF_DESC "SolarisAttrLongDesc"
#define _PROF_ATTRS "SolarisAttrKeyValue"
-#define _PROF_GETPROFNAME "(&(objectClass=SolarisProfAttr)(cn=%s))"
+/* Negate an exec_attr attribute to exclude exec_attr entries */
+#define _PROF_GETPROFNAME \
+"(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*))(cn=%s))"
#define _PROF_GETPROFNAME_SSD "(&(%%s)(cn=%s))"
static const char *prof_attrs[] = {
@@ -48,150 +49,88 @@ static const char *prof_attrs[] = {
_PROF_ATTRS,
(char *)NULL
};
-
-
+/*
+ * _nss_ldap_prof2str is the data marshaling method for the prof_attr
+ * system call getprofattr, getprofnam and getproflist.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * All:::Execute any command as the user or role:help=RtAll.html
+ *
+ */
static int
-_nss_ldap_prof2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_prof2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
- int buflen = (int)0;
+ int nss_result;
+ int buflen = 0;
unsigned long len = 0L;
- char *nullstring = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- profstr_t *prof = (profstr_t *)NULL;
- ns_ldap_attr_t *attrptr;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
+ char **name, **res1, **res2, **des, **attr;
+ char *res1_str, *res2_str, *des_str, *attr_str;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- prof = (profstr_t *)(argp->buf.result);
- ceiling = buffer + buflen;
- prof->name = (char *)NULL;
- prof->res1 = (char *)NULL;
- prof->res2 = (char *)NULL;
- prof->desc = (char *)NULL;
- prof->attr = (char *)NULL;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(argp->buf.buffer, 0, buflen);
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_prof2ent;
- }
-
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_prof2ent;
- }
- if (strcasecmp(attrptr->attrname, _PROF_NAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_prof2ent;
- }
- prof->name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- (void) strcpy(prof->name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROF_RES1) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- prof->res1 = nullstring;
- } else {
- prof->res1 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- (void) strcpy(prof->res1,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROF_RES2) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- prof->res2 = nullstring;
- } else {
- prof->res2 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- (void) strcpy(prof->res2,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROF_DESC) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- prof->desc = nullstring;
- } else {
- prof->desc = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- (void) strcpy(prof->desc,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROF_ATTRS) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- prof->attr = nullstring;
- } else {
- prof->attr = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_prof2ent;
- }
- (void) strcpy(prof->attr,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- }
+ buflen = argp->buf.buflen;
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getprofattr.c: _nss_ldap_prof2ent]\n");
- (void) fprintf(stdout, " prof-name: [%s]\n", prof->name);
- if (prof->res1 != (char *)NULL) {
- (void) fprintf(stdout, " res1: [%s]\n", prof->res1);
- }
- if (prof->res2 != (char *)NULL) {
- (void) fprintf(stdout, " res2: [%s]\n", prof->res2);
- }
- if (prof->desc != (char *)NULL) {
- (void) fprintf(stdout, " desc: [%s]\n", prof->desc);
+ name = __ns_ldap_getAttr(result->entry, _PROF_NAME);
+ if (name == NULL || name[0] == NULL ||
+ (strlen(name[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_prof2str;
}
- if (prof->attr != (char *)NULL) {
- (void) fprintf(stdout, " attr: [%s]\n", prof->attr);
+ res1 = __ns_ldap_getAttr(result->entry, _PROF_RES1);
+ if (res1 == NULL || res1[0] == NULL || (strlen(res1[0]) < 1))
+ res1_str = _NO_VALUE;
+ else
+ res1_str = res1[0];
+
+ res2 = __ns_ldap_getAttr(result->entry, _PROF_RES2);
+ if (res2 == NULL || res2[0] == NULL || (strlen(res2[0]) < 1))
+ res2_str = _NO_VALUE;
+ else
+ res2_str = res2[0];
+
+ des = __ns_ldap_getAttr(result->entry, _PROF_DESC);
+ if (des == NULL || des[0] == NULL || (strlen(des[0]) < 1))
+ des_str = _NO_VALUE;
+ else
+ des_str = des[0];
+
+ attr = __ns_ldap_getAttr(result->entry, _PROF_ATTRS);
+ if (attr == NULL || attr[0] == NULL || (strlen(attr[0]) < 1))
+ attr_str = _NO_VALUE;
+ else
+ attr_str = attr[0];
+ /* 5 = 4 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(res1_str) + strlen(res2_str) +
+ strlen(des_str) + strlen(attr_str) + 6;
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_prof2str;
}
-#endif /* DEBUG */
-result_prof2ent:
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_prof2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+ (void) snprintf(buffer, len, "%s:%s:%s:%s:%s",
+ name[0], res1_str, res2_str, des_str, attr_str);
+ /* The front end marshaller doesn't need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_prof2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
@@ -204,10 +143,6 @@ getbyname(ldap_backend_ptr be, void *a)
int ret;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getprofattr.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -243,11 +178,7 @@ _nss_ldap_prof_attr_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[getprofattr.c: _nss_ldap_prof_attr_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(profattr_ops,
sizeof (profattr_ops)/sizeof (profattr_ops[0]), _PROFATTR,
- prof_attrs, _nss_ldap_prof2ent));
+ prof_attrs, _nss_ldap_prof2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprojent.c b/usr/src/lib/nsswitch/ldap/common/getprojent.c
index fd332209d8..f1ff6db64e 100644
--- a/usr/src/lib/nsswitch/ldap/common/getprojent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getprojent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,220 +49,96 @@ static const char *project_attrs[] = {
(char *)NULL
};
-static char *
-gettok(char **nextpp, char sep)
-{
- char *p = *nextpp;
- char *q = p;
- char c;
-
- if (p == NULL)
- return (NULL);
- while ((c = *q) != '\0' && c != sep)
- q++;
- if (c == '\0')
- *nextpp = 0;
- else {
- *q++ = '\0';
- *nextpp = q;
- }
- return (p);
-}
-
/*
- * _nss_ldap_proj2ent is the data marshalling method for the project getXbyY
+ * _nss_ldap_proj2str is the data marshalling method for the project getXbyY
* (getprojbyname, getprojbyid, getprojent) backend processes. This method
* is called after a successful ldap search has been performed. This method
- * will parse the ldap search values into struct project = argp->buf.buffer
- * which the frontend routine expects. Three error conditions are expected
- * and returned to nsswitch.
+ * will parse the ldap search values into the file format.
+ * e.g.
+ *
+ * system:0:System:::
+ *
+ * beatles:100:The Beatles:john,paul,george,ringo::task.max-lwps=
+ * (privileged,100,signal=SIGTERM),(privileged,110,deny)
+ *
+ * (All in one line)
*/
static int
-_nss_ldap_proj2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_proj2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
+ int nss_result, buflen;
unsigned long len = 0;
- char **uglist;
- char *buffer, *ceiling;
- char *users, *groups, *p;
- struct project *proj;
+ char *buffer, *comment, *user_str, *group_str, *attr_str;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
+ char **name, **id, **descr, **users, **groups, **attr;
+
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = argp->buf.buflen;
- buffer = argp->buf.buffer;
- if (!argp->buf.result) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_proj2ent;
- }
nss_result = NSS_STR_PARSE_SUCCESS;
- proj = argp->buf.result;
- proj->pj_users = proj->pj_groups = NULL;
- proj->pj_attr = proj->pj_comment = NULL;
- ceiling = (char *)ROUND_DOWN(buffer + argp->buf.buflen,
- sizeof (char *));
- (void) memset(argp->buf.buffer, 0, argp->buf.buflen);
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_proj2ent;
- }
- len = strlen(attrptr->attrvalue[0]);
- if (strcasecmp(attrptr->attrname, _PROJ_NAME) == 0) {
- if (len == 0) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_proj2ent;
- }
- proj->pj_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- (void) strcpy(proj->pj_name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROJ_PROJID) == 0) {
- if (len == 0) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_proj2ent;
- }
- errno = 0;
- proj->pj_projid =
- (projid_t)strtol(attrptr->attrvalue[0],
- NULL, 10);
- if (errno != 0) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_proj2ent;
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROJ_DESCR) == 0) {
- proj->pj_comment = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- (void) strcpy(proj->pj_comment, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROJ_ATTR) == 0) {
- proj->pj_attr = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- (void) strcpy(proj->pj_attr, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROJ_USERS) == 0) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- users = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- (void) strcpy(users, attrptr->attrvalue[0]);
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- proj->pj_users = uglist = (char **)buffer;
- *uglist = NULL;
- while (uglist < (char **)ceiling) {
- p = gettok(&users, ',');
- if (p == NULL || *p == '\0') {
- *uglist++ = 0;
- break;
- }
- *uglist++ = p;
- }
- buffer = (char *)uglist;
- if (buffer >= ceiling)
- return (NSS_STR_PARSE_ERANGE);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PROJ_GROUPS) == 0) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- groups = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- (void) strcpy(groups, attrptr->attrvalue[0]);
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- proj->pj_groups = uglist = (char **)buffer;
- *uglist = NULL;
- while (uglist < (char **)ceiling) {
- p = gettok(&groups, ',');
- if (p == NULL || *p == '\0') {
- *uglist++ = 0;
- break;
- }
- *uglist++ = p;
- }
- buffer = (char *)uglist;
- if (buffer >= ceiling)
- return (NSS_STR_PARSE_ERANGE);
- continue;
- }
- }
- if (proj->pj_comment == NULL) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- proj->pj_comment = buffer;
- *buffer = '\0';
- buffer++;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ name = __ns_ldap_getAttr(result->entry, _PROJ_NAME);
+ if (name == NULL || name[0] == NULL || (strlen(name[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2str;
}
- if (proj->pj_users == NULL) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- proj->pj_users = (char **)buffer;
- *buffer = '\0';
- buffer++;
+ id = __ns_ldap_getAttr(result->entry, _PROJ_PROJID);
+ if (id == NULL || id[0] == NULL || (strlen(id[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2str;
}
- if (proj->pj_groups == NULL) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
- }
- proj->pj_groups = (char **)buffer;
- *buffer = '\0';
- buffer++;
+ descr = __ns_ldap_getAttr(result->entry, _PROJ_DESCR);
+ if (descr == NULL || descr[0] == NULL || (strlen(descr[0]) < 1))
+ comment = _NO_VALUE;
+
+ else
+ comment = descr[0];
+
+ users = __ns_ldap_getAttr(result->entry, _PROJ_USERS);
+ if (users == NULL || users[0] == NULL || (strlen(users[0]) < 1))
+ user_str = _NO_VALUE;
+
+ else
+ user_str = users[0];
+
+ groups = __ns_ldap_getAttr(result->entry, _PROJ_GROUPS);
+ if (groups == NULL || groups[0] == NULL || (strlen(groups[0]) < 1))
+ group_str = _NO_VALUE;
+
+ else
+ group_str = groups[0];
+
+ attr = __ns_ldap_getAttr(result->entry, _PROJ_ATTR);
+ if (attr == NULL || attr[0] == NULL || (strlen(attr[0]) < 1))
+ attr_str = _NO_VALUE;
+
+ else
+ attr_str = attr[0];
+
+ /* 6 = 5 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(id[0]) + strlen(comment) +
+ strlen(user_str) + strlen(group_str) + strlen(attr_str) + 6;
+ if (len >= buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2str;
}
- if (proj->pj_attr == NULL) {
- buffer = (char *)ROUND_UP(buffer, sizeof (char *));
- if (buffer >= ceiling) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_proj2ent;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2str;
}
- proj->pj_attr = buffer;
- *buffer = '\0';
- buffer++;
- }
+ buffer = be->buffer;
+ /* The front end marshaller does not need trailing nulls */
+ be->buflen = len - 1;
+ } else
+ buffer = argp->buf.buffer;
+
+ (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s", name[0], id[0],
+ comment, user_str, group_str, attr_str);
-result_proj2ent:
+result_proj2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
@@ -327,5 +202,5 @@ _nss_ldap_project_constr(const char *dummy1, const char *dummy2,
{
return (_nss_ldap_constr(project_ops,
sizeof (project_ops) / sizeof (project_ops[0]),
- _PROJECT, project_attrs, _nss_ldap_proj2ent));
+ _PROJECT, project_attrs, _nss_ldap_proj2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprotoent.c b/usr/src/lib/nsswitch/ldap/common/getprotoent.c
index 09522445e4..e9542a7543 100644
--- a/usr/src/lib/nsswitch/ldap/common/getprotoent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getprotoent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,181 +46,164 @@ static const char *protocols_attrs[] = {
(char *)NULL
};
+typedef struct protocol_alias {
+ char *protocol;
+ char *alias;
+} protocol_alias_t;
+
+static const protocol_alias_t ip_aliases[10] = {
+ { "ip", "IP" },
+ { "ipip", "IP-IP" },
+ { "ipcomp", "IPComp" },
+ { "ipv6", "IPv6" },
+ { "ipv6-route", "IPv6-Route" },
+ { "ipv6-frag", "IPv6-Frag" },
+ { "ipv6-icmp", "IPv6-ICMP" },
+ { "ipv6-nonxt", "IPv6-NoNxt" },
+ { "ipv6-opts", "IPv6-Opts" },
+ { NULL, NULL }
+};
/*
- * _nss_ldap_protocols2ent is the data marshaling method for the protocols
+ * When the data is imported by ldapaddent, it does not save the aliase in the
+ * "cn" that is same as the canonical name but only different in case.
+ * e.g.
+ * icmp 1 ICMP
+ *
+ * is saved as
+ *
+ * dn: cn=icmp, ...
+ * ...
+ * cn: icmp
+ * ...
+ *
+ * So it needs to replicate the canonical name as an alias of upper case.
+ * But some protocol does have different aliases.
+ *
+ * e.g.
+ * dn: cn=ospf, ...
+ * ...
+ * cn: ospf
+ * cn: OSPFIGP
+ * ...
+ *
+ * For many ip* protocols, the aliases are mixed cased. Maybe it's case
+ * insensitive. But this fucntion tries to restore the aliases to the original
+ * form as much as possible. If the alias can't be found in the aliases table,
+ * it assumes the alias is all upper case.
+ *
+ */
+static char *
+get_alias(char *protocol) {
+ int i;
+ char *cp;
+
+ if (strncmp(protocol, "ip", 2) == 0) {
+ for (i = 0; ip_aliases[i].protocol != NULL; i++) {
+ if (strcmp(protocol, ip_aliases[i].protocol) == 0)
+ return (ip_aliases[i].alias);
+ }
+ /*
+ * No aliase in the table. Return an all upper case aliase
+ */
+ for (cp = protocol; *cp; cp++)
+ *cp = toupper(*cp);
+
+ return (protocol);
+ } else {
+ /* Return an all upper case aliase */
+ for (cp = protocol; *cp; cp++)
+ *cp = toupper(*cp);
+
+ return (protocol);
+ }
+
+}
+/*
+ * _nss_ldap_protocols2str is the data marshaling method for the protocols
* getXbyY * (e.g., getbyname(), getbynumber(), getent()) backend processes.
* This method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into *proto = (struct
- * protoent *)argp->buf.result which the frontend process expects. Three error
- * conditions are expected and returned to nsswitch.
+ * This method will parse the ldap search values into a file format.
+ * e.g.
+ * idrp 45 IDRP
+ * or
+ * ospf 89 OSPFIGP
*/
static int
-_nss_ldap_protocols2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_protocols2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
+ uint_t i;
int nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char *cp, **mp, *cname = NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct protoent *proto = (struct protoent *)NULL;
+ int buflen = 0, len;
+ char *cname = NULL;
+ char *buffer = NULL, **number, *alias;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
+ ns_ldap_attr_t *names;
- buffer = (char *)argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pls2ent;
- }
- proto = (struct protoent *)argp->buf.result;
- ceiling = buffer + buflen;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ buflen = argp->buf.buflen;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
+ names = __ns_ldap_getAttrStruct(result->entry, _P_NAME);
+ if (names == NULL || names->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2str;
}
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
- }
- if (strcasecmp(attrptr->attrname, _P_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstime) {
- /* protocol name */
- cname = __s_api_get_canonical_name(
- result->entry, attrptr, 1);
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result =
- NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
- }
- proto->p_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_pls2ent;
- }
- (void) strcpy(proto->p_name, cname);
- mp = proto->p_aliases =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)proto->p_aliases +
- sizeof (char *) *
- (attrptr->value_count + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_pls2ent;
- }
- firstime = (int)0;
- }
- /* alias list */
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
- }
- /*
- * When the data is imported by ldapaddent,
- * it does not save the aliase in the "cn"
- * that is same as the canonical name but only
- * differnt in case.
- * e.g.
- * icmp 1 ICMP
- *
- * is saved as
- *
- * dn: cn=icmp, ...
- * ...
- * cn: icmp
- * ...
- * So it needs to replicate the canonical name
- * as an aliase of upper case.
- *
- * But in the case of
- * ospf 89 OSPFIGP
- * it creates a redundant aliase.
- * e.g.
- * dn: cn=icmp, ...
- * ...
- * cn: ospf
- * cn: OSPFIGP
- * ...
- *
- * getent services ospf
- * ==> ospf 89 ospf OSPFIGP
- *
- * Some condition check is added to handle this
- * scenario. Such check also works with
- * following scenario.
- * dn: cn=icmp, ...
- * ...
- * cn: icmp
- * cn: ICMP
- * ...
- */
- if (strcmp(proto->p_name,
- attrptr->attrvalue[j]) == 0) {
- if (attrptr->value_count > 1)
- /* Do not replicate */
- continue;
- for (cp = attrptr->attrvalue[j];
- *cp; cp++)
- *cp = toupper(*cp);
- }
- *mp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pls2ent;
- }
- (void) strcpy(*mp++, attrptr->attrvalue[j]);
- continue;
- }
- }
- if (strcasecmp(attrptr->attrname, _P_PROTO) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
+ /* Get the canonical name */
+ cname = __s_api_get_canonical_name(result->entry, names, 1);
+ if (cname == NULL || (len = strlen(cname)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2str;
+ }
+ number = __ns_ldap_getAttr(result->entry, _P_PROTO);
+ if (number == NULL || number[0] == NULL ||
+ (len = strlen(number[0])) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2str;
+ }
+ len = snprintf(buffer, buflen, "%s %s", cname, number[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
+ /* Append aliases */
+ if (names->value_count == 1) {
+ /* create an aliase from protocol name */
+ alias = get_alias(cname);
+ len = snprintf(buffer, buflen, " %s", alias);
+ TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
+
+ } else {
+ for (i = 0; i < names->value_count; i++) {
+ if (names->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2str;
}
- errno = 0;
- proto->p_proto = (int)strtol(attrptr->attrvalue[0],
- (char **)NULL, 10);
- if (errno != 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pls2ent;
+ /* Skip the canonical name */
+ if (strcasecmp(names->attrvalue[i], cname) != 0) {
+ len = snprintf(buffer, buflen, " %s",
+ names->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen,
+ result_pls2str);
}
- continue;
}
}
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getprotoent.c: _nss_ldap_protocols2ent]\n");
- (void) fprintf(stdout, " p_name: [%s]\n", proto->p_name);
- if (mp != NULL) {
- for (mp = proto->p_aliases; *mp != NULL; mp++)
- (void) fprintf(stdout, " p_aliases: [%s]\n", *mp);
- }
- (void) fprintf(stdout, " p_proto: [%d]\n", proto->p_proto);
-#endif /* DEBUG */
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
-result_pls2ent:
+result_pls2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
@@ -323,5 +305,5 @@ _nss_ldap_protocols_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(proto_ops,
sizeof (proto_ops)/sizeof (proto_ops[0]), _PROTOCOLS,
- protocols_attrs, _nss_ldap_protocols2ent));
+ protocols_attrs, _nss_ldap_protocols2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getpwnam.c b/usr/src/lib/nsswitch/ldap/common/getpwnam.c
index 205513812a..a2c9ff40c9 100644
--- a/usr/src/lib/nsswitch/ldap/common/getpwnam.c
+++ b/usr/src/lib/nsswitch/ldap/common/getpwnam.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -58,190 +57,106 @@ static const char *pwd_attrs[] = {
(char *)NULL
};
-
/*
- * _nss_ldap_passwd2ent is the data marshaling method for the passwd getXbyY
+ * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY
* (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
* called after a successful ldap search has been performed. This method will
- * parse the ldap search values into struct passwd = argp->buf.buffer which
- * the frontend process expects. Three error conditions are expected and
- * returned to nsswitch.
+ * parse the ldap search values into the file format.
+ * e.g.
+ *
+ * nobody:x:60001:60001:Nobody:/:
+ *
*/
-
static int
-_nss_ldap_passwd2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i = 0;
int nss_result;
- int buflen = (int)0;
- unsigned long len = 0L;
- char *buffer = (char *)NULL;
- char *ptr2x;
- char *ceiling = (char *)NULL;
- char *nullstring = (char *)NULL;
- struct passwd *pwd = (struct passwd *)NULL;
+ int buflen = 0;
+ unsigned long str_len = 0L;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
- int have_uid = 0;
- int have_uidn = 0;
- int have_gidn = 0;
+ ns_ldap_entry_t *entry;
+ char **uid_v, **uidn_v, **gidn_v;
+ char **gecos_v, **homedir_v, **shell_v;
+ char *NULL_STR = "";
+
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n");
-#endif /* DEBUG */
+ entry = result->entry;
+ buflen = argp->buf.buflen;
buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pwd2ent;
- }
- pwd = (struct passwd *)argp->buf.result;
- ceiling = buffer + buflen;
- nullstring = (buffer + (buflen - 1));
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(buffer, 0, buflen);
- /*
- * need to always return password as "x"
- * so put "x" at top of the buffer
- */
- ptr2x = buffer;
- *buffer++ = 'x';
- *buffer++ = '\0';
-
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pwd2ent;
- }
-
- pwd->pw_gecos = nullstring;
- pwd->pw_dir = nullstring;
- pwd->pw_shell = nullstring;
+ /* 8 = 6 ':' + 1 '\0' + 1 'x' */
+ buflen -= 8;
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pwd2ent;
- }
- if (strcasecmp(attrptr->attrname, _PWD_UID) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pwd2ent;
- }
- pwd->pw_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pwd2ent;
- }
- (void) strcpy(pwd->pw_name, attrptr->attrvalue[0]);
- have_uid = 1;
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PWD_UIDNUMBER) == 0) {
- if (attrptr->attrvalue[0] == '\0') {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pwd2ent;
- }
- pwd->pw_uid = strtol(attrptr->attrvalue[0],
- (char **)NULL, 10);
- have_uidn = 1;
- continue;
- }
- if (strcasecmp(attrptr->attrname, _PWD_GIDNUMBER) == 0) {
- if (attrptr->attrvalue[0] == '\0') {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_pwd2ent;
- }
- pwd->pw_gid = strtol(attrptr->attrvalue[0],
- (char **)NULL, 10);
- have_gidn = 1;
- continue;
- }
- if ((strcasecmp(attrptr->attrname, _PWD_GECOS) == 0) &&
- (attrptr->value_count > 0)) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- pwd->pw_gecos = nullstring;
- } else {
- pwd->pw_gecos = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pwd2ent;
- }
- (void) strcpy(pwd->pw_gecos,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if ((strcasecmp(attrptr->attrname, _PWD_HOMEDIRECTORY) == 0) &&
- (attrptr->value_count > 0)) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- pwd->pw_dir = nullstring;
- } else {
- pwd->pw_dir = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pwd2ent;
- }
- (void) strcpy(pwd->pw_dir,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if ((strcasecmp(attrptr->attrname, _PWD_LOGINSHELL) == 0) &&
- (attrptr->value_count > 0)) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- pwd->pw_shell = nullstring;
- } else {
- pwd->pw_shell = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_pwd2ent;
- }
- (void) strcpy(pwd->pw_shell,
- attrptr->attrvalue[0]);
- }
- continue;
- }
+ uid_v = __ns_ldap_getAttr(entry, _PWD_UID);
+ uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER);
+ gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER);
+ if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL ||
+ uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pwd2str;
+ }
+ str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]);
+ if (str_len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_pwd2str;
}
- /* error if missing required attributes */
- if (have_uid == 0 || have_uidn == 0 || have_gidn == 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
+ gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS);
+ if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
+ gecos_v = &NULL_STR;
+ else
+ str_len += strlen(gecos_v[0]);
+
+ homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY);
+ if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
+ homedir_v = &NULL_STR;
+ else
+ str_len += strlen(homedir_v[0]);
+
+ shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL);
+ if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
+ shell_v = &NULL_STR;
+ else
+ str_len += strlen(shell_v[0]);
+
+ if (str_len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_pwd2str;
}
- pwd->pw_age = nullstring;
- pwd->pw_comment = nullstring;
- pwd->pw_passwd = ptr2x;
+ if (argp->buf.result != NULL) {
+ be->buflen = str_len + 8;
+ be->buffer = malloc(be->buflen);
+ if (be->buffer == NULL) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2str;
+ }
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n");
- (void) fprintf(stdout, " pw_name: [%s]\n", pwd->pw_name);
- (void) fprintf(stdout, " pw_uid: [%ld]\n", pwd->pw_uid);
- (void) fprintf(stdout, " pw_gid: [%ld]\n", pwd->pw_gid);
- (void) fprintf(stdout, " pw_gecos: [%s]\n", pwd->pw_gecos);
- (void) fprintf(stdout, " pw_dir: [%s]\n", pwd->pw_dir);
- (void) fprintf(stdout, " pw_shell: [%s]\n", pwd->pw_shell);
-#endif /* DEBUG */
+ (void) snprintf(be->buffer, be->buflen,
+ "%s:%s:%s:%s:%s:%s:%s",
+ uid_v[0], "x", uidn_v[0], gidn_v[0],
+ gecos_v[0], homedir_v[0], shell_v[0]);
+ } else {
+ (void) snprintf(argp->buf.buffer, (str_len + 8),
+ "%s:%s:%s:%s:%s:%s:%s",
+ uid_v[0], "x", uidn_v[0], gidn_v[0],
+ gecos_v[0], homedir_v[0], shell_v[0]);
-result_pwd2ent:
+ }
+
+result_pwd2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
-
/*
* getbyname gets a passwd entry by uid name. This function constructs an ldap
* search filter using the name invocation parameter and the getpwnam search
@@ -259,10 +174,6 @@ getbyname(ldap_backend_ptr be, void *a)
char name[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -296,10 +207,6 @@ getbyuid(ldap_backend_ptr be, void *a)
char userdata[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: getbyuid]\n");
-#endif /* DEBUG */
-
ret = snprintf(searchfilter, sizeof (searchfilter),
_F_GETPWUID, (long)argp->key.uid);
if (ret >= sizeof (searchfilter) || ret < 0)
@@ -337,11 +244,7 @@ _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd_constr]\n");
-#endif /* DEBUG */
-
return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
sizeof (passwd_ops)/sizeof (passwd_ops[0]),
- _PASSWD, pwd_attrs, _nss_ldap_passwd2ent));
+ _PASSWD, pwd_attrs, _nss_ldap_passwd2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getrpcent.c b/usr/src/lib/nsswitch/ldap/common/getrpcent.c
index e8e0d51df3..3419d93fb6 100644
--- a/usr/src/lib/nsswitch/ldap/common/getrpcent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getrpcent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,144 +46,86 @@ static const char *rpc_attrs[] = {
};
/*
- * _nss_ldap_rpc2ent is the data marshaling method for the rpc getXbyY
+ * _nss_ldap_rpc2str is the data marshaling method for the rpc getXbyY
* (e.g., getbyname(), getbynumber(), getrpcent()) backend processes.
* This method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into *rpc = (struct
- * rpcent *)argp->buf.result which the frontend process expects. Three
- * error conditions are expected and returned to nsswitch.
+ * This method will parse the ldap search values into the file format.
+ * e.g.
+ *
+ * nfs_acl 100227
+ * snmp 100122 na.snmp snmp-cmc snmp-synoptics snmp-unisys snmp-utk
*/
-
static int
-_nss_ldap_rpc2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_rpc2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j;
+ uint_t i;
int nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char **mp, *cname = NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct rpcent *rpc = (struct rpcent *)NULL;
+ int buflen = 0, len;
+ char *cname = NULL;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
-
- buffer = (char *)argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_rpc2ent;
- }
- rpc = (struct rpcent *)argp->buf.result;
- ceiling = buffer + buflen;
+ ns_ldap_attr_t *names;
+ char **rpcnumber;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
- }
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
+ buflen = argp->buf.buflen;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_rpc2str;
}
- if (strcasecmp(attrptr->attrname, _R_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- /* traverse for all multivalued values */
- if (firstime) {
- /* rpc name */
- cname = __s_api_get_canonical_name(
- result->entry, attrptr, 1);
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result =
- NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
- }
- rpc->r_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_rpc2ent;
- }
- (void) strcpy(rpc->r_name, cname);
- /* alias list */
- mp = rpc->r_aliases =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)rpc->r_aliases +
- sizeof (char *) *
- (attrptr->value_count + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_rpc2ent;
- }
- firstime = (int)0;
- }
- /* alias list */
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
- }
- /* skip canonical name */
- if (strcmp(attrptr->attrvalue[j], cname) == 0)
- continue;
- *mp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_rpc2ent;
- }
- (void) strcpy(*mp++, attrptr->attrvalue[j]);
- continue;
- }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+
+ names = __ns_ldap_getAttrStruct(result->entry, _R_NAME);
+ if (names == NULL || names->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_rpc2str;
+ }
+ /* Get the canonical rpc name */
+ cname = __s_api_get_canonical_name(result->entry, names, 1);
+ if (cname == NULL || (len = strlen(cname)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_rpc2str;
+ }
+ rpcnumber = __ns_ldap_getAttr(result->entry, _R_NUMBER);
+ if (rpcnumber == NULL || rpcnumber[0] == NULL ||
+ (len = strlen(rpcnumber[0])) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_rpc2str;
+ }
+ len = snprintf(buffer, buflen, "%s %s", cname, rpcnumber[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_rpc2str);
+ /* Append aliases */
+ for (i = 0; i < names->value_count; i++) {
+ if (names->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_rpc2str;
}
- if (strcasecmp(attrptr->attrname, _R_NUMBER) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
- }
- errno = 0;
- rpc->r_number = (int)strtol(attrptr->attrvalue[0],
- (char **)NULL, 10);
- if (errno != 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_rpc2ent;
- }
- continue;
+ /* Skip the canonical name */
+ if (strcasecmp(names->attrvalue[i], cname) != 0) {
+ len = snprintf(buffer, buflen, " %s",
+ names->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_rpc2str);
}
}
- if (mp != NULL)
- *mp = NULL;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getrpcent.c: _nss_ldap_rpc2ent]\n");
- (void) fprintf(stdout, " r_name: [%s]\n", rpc->r_name);
- if (mp != NULL) {
- for (mp = rpc->r_aliases; *mp != NULL; mp++)
- (void) fprintf(stdout, " r_aliases: [%s]\n", *mp);
- }
- (void) fprintf(stdout, " r_number: [%d]\n", rpc->r_number);
-#endif /* DEBUG */
-result_rpc2ent:
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_rpc2str:
(void) __ns_ldap_freeResult(&be->result);
- return ((int)nss_result);
+ return (nss_result);
}
-
/*
* getbyname gets struct rpcent values by rpc name. This function
* constructs an ldap search filter using the rpc name invocation
@@ -276,5 +217,5 @@ _nss_ldap_rpc_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(rpc_ops,
sizeof (rpc_ops)/sizeof (rpc_ops[0]),
- _RPC, rpc_attrs, _nss_ldap_rpc2ent));
+ _RPC, rpc_attrs, _nss_ldap_rpc2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getservent.c b/usr/src/lib/nsswitch/ldap/common/getservent.c
index e266a31b42..9d83298fbc 100644
--- a/usr/src/lib/nsswitch/ldap/common/getservent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getservent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -91,14 +90,15 @@ _nss_services_cookie_new(ns_ldap_result_t *result, int index, char *cname) {
return (cookie);
}
-
/*
- * _nss_ldap_services2ent is the data marshaling method for the services
+ * _nss_ldap_services2str is the data marshaling method for the services
* getXbyY * (e.g., getbyname(), getbyport(), getent()) backend processes.
* This method is called after a successful ldap search has been performed.
- * This method will parse the ldap search values into *serv = (struct
- * servent *)argp->buf.result which the frontend process expects. Three error
- * conditions are expected and returned to nsswitch.
+ * This method will parse the ldap search values into the file format.
+ * e.g.
+ *
+ * nfsd 2049/udp nfs
+ * nfsd 2049/tcp nfs
*
* In section 5.5 of RFC 2307, it specifies that a "services" LDAP entry
* containing multiple ipserviceprotocol values should be able to be mapped
@@ -107,30 +107,18 @@ _nss_services_cookie_new(ns_ldap_result_t *result, int index, char *cname) {
*/
static int
-_nss_ldap_services2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_services2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, j, k;
+ uint_t i, k;
int nss_result;
- int buflen = (int)0;
- int firstime = (int)1;
- unsigned long len = 0L;
- char **mp, *cname = NULL, *protoval = NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- struct servent *serv = (struct servent *)NULL;
+ int buflen = 0, len;
+ char **ipport, *cname = NULL, *protoval = NULL;
+ char *buffer = NULL;
ns_ldap_result_t *result;
- ns_ldap_attr_t *attrptr, *protocol = NULL;
+ ns_ldap_attr_t *names = NULL, *protocol = NULL;
_nss_services_cookie_t *cookie = (_nss_services_cookie_t *)
be->services_cookie;
- buffer = (char *)argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- serv = (struct servent *)argp->buf.result;
- ceiling = buffer + buflen;
-#ifdef DEBUG
- (void) fprintf(stderr, "[getservent.c: _nss_ldap_services2ent]\n");
-#endif /* DEBUG */
-
if (cookie) {
/*
* getservent_r with multiple protocol values and the entry
@@ -146,160 +134,123 @@ _nss_ldap_services2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
*/
result = be->result;
}
+ if (result == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+
+ buflen = argp->buf.buflen;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
+ /* Get services names */
+ names = __ns_ldap_getAttrStruct(result->entry, _S_NAME);
+ if (names == NULL || names->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ /* Get canonical services name */
+ if (cname == NULL) {
+ cname = __s_api_get_canonical_name(result->entry, names, 1);
+ if (cname == NULL || (len = strlen(cname)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ }
+ /* Get port */
+ ipport = __ns_ldap_getAttr(result->entry, _S_PORT);
+ if (ipport == NULL || ipport[0] == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ /* Set services name and port and '/' */
+ len = snprintf(buffer, buflen, "%s %s/", cname, ipport[0]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_srvs2str);
+
+ /* Get protocol */
+ protocol = __ns_ldap_getAttrStruct(result->entry, _S_PROTOCOL);
+ if (protocol == NULL || protocol->attrvalue == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
}
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- if (strcasecmp(attrptr->attrname, _S_NAME) == 0) {
- for (j = 0; j < attrptr->value_count; j++) {
- if (firstime) {
- /* service name */
- if (cname == NULL) {
- cname = __s_api_get_canonical_name(
- result->entry, attrptr, 1);
- }
- if (cname == NULL ||
- (len = strlen(cname)) < 1) {
- nss_result =
- NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- serv->s_name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_srvs2ent;
- }
- (void) strcpy(serv->s_name, cname);
- /* alias list */
- mp = serv->s_aliases =
- (char **)ROUND_UP(buffer,
- sizeof (char **));
- buffer = (char *)serv->s_aliases +
- sizeof (char *) *
- (attrptr->value_count + 1);
- buffer = (char *)ROUND_UP(buffer,
- sizeof (char **));
- if (buffer >= ceiling) {
- nss_result =
- (int)NSS_STR_PARSE_ERANGE;
- goto result_srvs2ent;
- }
- firstime = (int)0;
- }
- /* alias list */
- if ((attrptr->attrvalue[j] == NULL) ||
- (len = strlen(attrptr->attrvalue[j])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- /* skip canonical name */
- if (strcmp(cname, attrptr->attrvalue[j]) == 0)
- continue;
-
- *mp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_srvs2ent;
- }
- (void) strcpy(*mp++, attrptr->attrvalue[j]);
- continue;
- }
- }
- if (strcasecmp(attrptr->attrname, _S_PORT) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
+ if (cookie) {
+ /*
+ * getservent_r
+ * Get current value then increment index
+ */
+ protoval = protocol->attrvalue[cookie->index++];
+ } else if (protocol->value_count > 1 && be->setcalled == 0 &&
+ argp->key.serv.proto) {
+ /*
+ * getserverbyname_r and getservbyport_r
+ *
+ * If there are more than one value and
+ * it needs to match protocol too,
+ * iterate each value to find matching one.
+ */
+ for (k = 0; k < protocol->value_count; k++) {
+ if (protocol->attrvalue[k] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ if (strcmp(protocol->attrvalue[k],
+ argp->key.serv.proto) == 0) {
+ protoval = protocol->attrvalue[k];
+ break;
}
- serv->s_port =
- htons((ushort_t)atoi(attrptr->attrvalue[0]));
- continue;
}
+ } else {
+ /*
+ * 1. getserverbyname_r and getservbyport_r
+ *
+ * It does not need to match protocol or
+ * ipserviceprotocol has single value,
+ * return the first one.
+ *
+ * 2. getservent_r with single ipserviceprotocol value
+ * or multiple values and the entry is
+ * enumerated 1st time, return the first one.
+ *
+ */
+ protoval = protocol->attrvalue[0];
+ }
- if (strcasecmp(attrptr->attrname, _S_PROTOCOL) == 0) {
- /* protocol name */
- if (attrptr->attrvalue == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- protocol = attrptr;
- if (cookie) {
- /*
- * getservent_r
- * Get current value then increment index
- */
- protoval = attrptr->attrvalue[cookie->index++];
- } else if (attrptr->value_count > 1 &&
- argp->key.serv.proto) {
- /*
- * getserverbyname_r and getservbyport_r
- *
- * If there are more than one value and
- * it needs to match protocol too,
- * iterate each value to find matching one.
- * getservent_r sets key.serv.proto to NULL,
- * so it wouldn't run this part of code.
- */
- for (k = 0; k < attrptr->value_count; k++) {
- if (attrptr->attrvalue[k] == NULL) {
- nss_result =
- NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- if (strcmp(attrptr->attrvalue[k],
- argp->key.serv.proto) == 0) {
- protoval =
- attrptr->attrvalue[k];
- break;
- }
- }
- } else {
- /*
- * 1. getserverbyname_r and getservbyport_r
- *
- * It does not need to match protocol or
- * ipserviceprotocol has single value,
- * return the first one
- *
- * 2. getservent_r with single value
- * or multiple values and the entry is
- * enumerated 1st time,
- * return the first one
- *
- */
- protoval = attrptr->attrvalue[0];
- }
+ if (protoval == NULL || (len = strlen(protoval)) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
- if (protoval == NULL || (len = strlen(protoval)) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
- }
- serv->s_proto = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_srvs2ent;
- }
- (void) strcpy(serv->s_proto, protoval);
- continue;
+ /* Set protocol */
+ len = snprintf(buffer, buflen, "%s", protoval);
+ TEST_AND_ADJUST(len, buffer, buflen, result_srvs2str);
+
+ /* Append aliases */
+ for (i = 0; i < names->value_count; i++) {
+ if (names->attrvalue[i] == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2str;
+ }
+ /* Skip the canonical name */
+ if (strcmp(cname, names->attrvalue[i]) != 0) {
+ len = snprintf(buffer, buflen, " %s",
+ names->attrvalue[i]);
+ TEST_AND_ADJUST(len, buffer, buflen, result_srvs2str);
}
}
+
if (be->enumcookie != NULL && cookie == NULL &&
protocol->value_count > 1) {
/*
@@ -314,25 +265,18 @@ _nss_ldap_services2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
(void *)_nss_services_cookie_new(be->result, 1, cname);
if (be->services_cookie == NULL) {
nss_result = NSS_STR_PARSE_PARSE;
- goto result_srvs2ent;
+ goto result_srvs2str;
}
/* reset be->result so it won't get freed later */
be->result = NULL;
}
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getservent.c: _nss_ldap_services2ent]\n");
- (void) fprintf(stdout, " s_name: [%s]\n", serv->s_name);
- if (mp != NULL) {
- for (mp = serv->s_aliases; *mp != NULL; mp++)
- (void) fprintf(stdout, " s_aliases: [%s]\n", *mp);
- }
- (void) fprintf(stdout, " s_port: [%d]\n", serv->s_port);
- (void) fprintf(stdout, " s_protocol: [%s]\n", serv->s_proto);
-#endif /* DEBUG */
+ /* The front end marshaller doesn't need to copy trailing nulls */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
-result_srvs2ent:
+result_srvs2str:
if (cookie) {
/*
* getservent_r with multiple ipserviceprotocol values and
@@ -356,10 +300,9 @@ result_srvs2ent:
*/
(void) __ns_ldap_freeResult(&be->result);
}
- return ((int)nss_result);
+ return (nss_result);
}
-
/*
* getbyname gets struct servent values by service name. This
* function constructs an ldap search filter using the service
@@ -498,5 +441,5 @@ _nss_ldap_services_constr(const char *dummy1, const char *dummy2,
return ((nss_backend_t *)_nss_ldap_constr(serv_ops,
sizeof (serv_ops)/sizeof (serv_ops[0]), _SERVICES,
- services_attrs, _nss_ldap_services2ent));
+ services_attrs, _nss_ldap_services2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getspent.c b/usr/src/lib/nsswitch/ldap/common/getspent.c
index cf5ea84652..dc93c5d9ca 100644
--- a/usr/src/lib/nsswitch/ldap/common/getspent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getspent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,7 +30,6 @@
#include "ldap_common.h"
/* shadow attributes filters */
-#define _S_CN "cn"
#define _S_UID "uid"
#define _S_USERPASSWORD "userpassword"
#define _S_FLAG "shadowflag"
@@ -46,185 +44,105 @@ static const char *sp_attrs[] = {
(char *)NULL
};
-
-extern ns_ldap_attr_t *getattr(ns_ldap_result_t *result, int i);
-
/*
- * _nss_ldap_shadow2ent is the data marshaling method for the passwd getXbyY
+ * _nss_ldap_shadow2str is the data marshaling method for the shadow getXbyY
* (e.g., getspnam(), getspent()) backend processes. This method is called after
* a successful ldap search has been performed. This method will parse the
- * ldap search values into struct spwd = argp->buf.buffer which the frontend
- * process expects. Three error conditions are expected and returned to
- * nsswitch.
+ * ldap search values into the file format.
+ * e.g.
+ *
+ * myname:gaBXNJuz4JDmA:6445::::::
+ *
*/
static int
-_nss_ldap_shadow2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_shadow2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i = 0;
int nss_result;
- int buflen = (int)0;
+ int buflen = 0;
unsigned long len = 0L;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- char *pw_passwd = (char *)NULL;
- char *nullstring = (char *)NULL;
+ char *tmp, *buffer = NULL;
+ char *pw_passwd = NULL;
char np[] = "*NP*";
ns_ldap_result_t *result = be->result;
- ns_ldap_attr_t *attrptr;
- long ltmp = (long)0L;
- struct spwd *spd = (struct spwd *)NULL;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
-#endif /* DEBUG */
+ char **uid, **passwd, **flag, *flag_str;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_spd2ent;
- }
- spd = (struct spwd *)argp->buf.result;
- ceiling = buffer + buflen;
- nullstring = (buffer + (buflen - 1));
-
- /* Default values */
- spd->sp_lstchg = -1; spd->sp_min = -1;
- spd->sp_max = -1; spd->sp_warn = -1;
- spd->sp_inact = -1; spd->sp_expire = -1;
- spd->sp_flag = 0; spd->sp_pwdp = NULL;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ buflen = argp->buf.buflen;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
- (void) memset(buffer, 0, buflen);
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_spd2ent;
+ uid = __ns_ldap_getAttr(result->entry, _S_UID);
+ if (uid == NULL || uid[0] == NULL || (strlen(uid[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_spd2str;
}
-
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (strcasecmp(attrptr->attrname, _S_UID) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_spd2ent;
- }
- spd->sp_namp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_spd2ent;
- }
- (void) strcpy(spd->sp_namp, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _S_USERPASSWORD) == 0) {
- if (attrptr->attrvalue[0] == '\0') {
- spd->sp_pwdp = nullstring;
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_spd2ent;
- }
- pw_passwd = attrptr->attrvalue[0];
- if (pw_passwd) {
- char *tmp;
-
- if ((tmp = strstr(pw_passwd, "{crypt}"))
- != NULL) {
- if (tmp != pw_passwd)
- pw_passwd = np;
- else
- pw_passwd += 7;
- } else if ((tmp = strstr(pw_passwd, "{CRYPT}"))
- != NULL) {
- if (tmp != pw_passwd)
- pw_passwd = np;
- else
- pw_passwd += 7;
- } else {
- pw_passwd = np;
- }
- }
- len = (unsigned long)strlen(pw_passwd);
- if (len < 1) {
- spd->sp_pwdp = nullstring;
- } else {
- spd->sp_pwdp = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_spd2ent;
- }
- }
- (void) strcpy(spd->sp_pwdp, pw_passwd);
- }
-
- /*
- * Ignore the following password aging related attributes:
- * -- shadowlastchange
- * -- shadowmin
- * -- shadowmax
- * -- shadowwarning
- * -- shadowinactive
- * -- shadowexpire
- * This is because the LDAP naming service does not
- * really support the password aging fields defined
- * in the shadow structure. These fields, sp_lstchg,
- * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
- * have been set to -1.
- */
-
- if (strcasecmp(attrptr->attrname, _S_FLAG) == 0) {
- if (attrptr->attrvalue[0] == '\0') {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_spd2ent;
- }
- errno = 0;
- ltmp = strtol(attrptr->attrvalue[0], (char **)NULL, 10);
- if (errno != 0) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_spd2ent;
- }
- spd->sp_flag = (int)ltmp;
- continue;
+ len += strlen(uid[0]);
+
+ passwd = __ns_ldap_getAttr(result->entry, _S_USERPASSWORD);
+ if (passwd == NULL || passwd[0] == NULL || strlen(passwd[0]) < 1) {
+ pw_passwd = _NO_VALUE;
+ } else {
+ if ((tmp = strstr(passwd[0], "{crypt}")) != NULL ||
+ (tmp = strstr(passwd[0], "{CRYPT}")) != NULL) {
+ if (tmp != passwd[0])
+ pw_passwd = np;
+ else
+ pw_passwd = tmp + strlen("{crypt}");
+ } else {
+ /* Replace it with *NP* */
+ pw_passwd = np;
}
}
-
- /* we will not allow for an empty password to be */
- /* returned to the front end as this is not a supported */
- /* configuration. Since we got to this point without */
- /* the password being set, we assume that no password was */
- /* set on the server which is consider a misconfiguration. */
- /* We will proceed and set the password to *NP* as no password */
- /* is not supported */
-
- if (spd->sp_pwdp == NULL) {
- spd->sp_pwdp = buffer;
- buffer += strlen(np) + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_spd2ent;
- }
- strcpy(spd->sp_pwdp, np);
+ len += strlen(pw_passwd);
+
+ /*
+ * Ignore the following password aging related attributes:
+ * -- shadowlastchange
+ * -- shadowmin
+ * -- shadowmax
+ * -- shadowwarning
+ * -- shadowinactive
+ * -- shadowexpire
+ * This is because the LDAP naming service does not
+ * really support the password aging fields defined
+ * in the shadow structure. These fields, sp_lstchg,
+ * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
+ * will be set to -1 by the front end marshaller.
+ */
+ flag = __ns_ldap_getAttr(result->entry, _S_FLAG);
+ if (flag == NULL || flag[0] == NULL)
+ flag_str = _NO_VALUE;
+ else
+ flag_str = flag[0];
+
+ /* 9 = 8 ':' + 1 '\0' */
+ len += strlen(flag_str) + 9;
+
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_spd2str;
}
+ if (argp->buf.result != NULL) {
+ be->buffer = calloc(1, len);
+ if (be->buffer == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_spd2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
- (void) fprintf(stdout, " sp_namp: [%s]\n", spd->sp_namp);
- (void) fprintf(stdout, " sp_pwdp: [%s]\n", spd->sp_pwdp);
- (void) fprintf(stdout, " sp_latchg: [%d]\n", spd->sp_lstchg);
- (void) fprintf(stdout, " sp_min: [%d]\n", spd->sp_min);
- (void) fprintf(stdout, " sp_max: [%d]\n", spd->sp_max);
- (void) fprintf(stdout, " sp_warn: [%d]\n", spd->sp_warn);
- (void) fprintf(stdout, " sp_inact: [%d]\n", spd->sp_inact);
- (void) fprintf(stdout, " sp_expire: [%d]\n", spd->sp_expire);
- (void) fprintf(stdout, " sp_flag: [%d]\n", spd->sp_flag);
-#endif /* DEBUG */
+ (void) snprintf(buffer, len, "%s:%s:::::::%s",
+ uid[0], pw_passwd, flag_str);
-result_spd2ent:
+ /* The front end marhsaller doesn't need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+result_spd2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
@@ -245,13 +163,8 @@ getbynam(ldap_backend_ptr be, void *a)
char searchfilter[SEARCHFILTERLEN];
char userdata[SEARCHFILTERLEN];
char name[SEARCHFILTERLEN + 1];
- int len;
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getspent.c: getbynam]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -288,11 +201,7 @@ _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2,
const char *dummy3)
{
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow_constr]\n");
-#endif /* DEBUG */
-
return ((nss_backend_t *)_nss_ldap_constr(sp_ops,
sizeof (sp_ops)/sizeof (sp_ops[0]),
- _SHADOW, sp_attrs, _nss_ldap_shadow2ent));
+ _SHADOW, sp_attrs, _nss_ldap_shadow2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/getuserattr.c b/usr/src/lib/nsswitch/ldap/common/getuserattr.c
index d36194d27e..c804a92187 100644
--- a/usr/src/lib/nsswitch/ldap/common/getuserattr.c
+++ b/usr/src/lib/nsswitch/ldap/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,149 +49,87 @@ static const char *user_attrs[] = {
_USER_ATTRS,
(char *)NULL
};
-
-
+/*
+ * _nss_ldap_user2str is the data marshaling method for the user_attr
+ * system call getuserattr, getusernam and getuseruid.
+ * This method is called after a successful search has been performed.
+ * This method will parse the search results into the file format.
+ * e.g.
+ *
+ * adm::::profiles=Log Management
+ *
+ */
static int
-_nss_ldap_user2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_user2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
- int buflen = (int)0;
+ int nss_result;
+ int buflen = 0;
unsigned long len = 0L;
- char *nullstring = (char *)NULL;
- char *buffer = (char *)NULL;
- char *ceiling = (char *)NULL;
- userstr_t *user = (userstr_t *)NULL;
- ns_ldap_attr_t *attrptr;
+ char *buffer = NULL;
ns_ldap_result_t *result = be->result;
+ char **name, **res1, **res2, **qu, **attr;
+ char *res1_str, *res2_str, *qu_str, *attr_str;
- buffer = argp->buf.buffer;
- buflen = (size_t)argp->buf.buflen;
- if (!argp->buf.result) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- user = (userstr_t *)(argp->buf.result);
- ceiling = buffer + buflen;
- user->name = (char *)NULL;
- user->qualifier = (char *)NULL;
- user->res1 = (char *)NULL;
- user->res2 = (char *)NULL;
- user->attr = (char *)NULL;
- nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+
+ buflen = argp->buf.buflen;
+ nss_result = NSS_STR_PARSE_SUCCESS;
(void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_user2ent;
+ name = __ns_ldap_getAttr(result->entry, _USER_NAME);
+ if (name == NULL || name[0] == NULL ||
+ (strlen(name[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_user2str;
}
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_user2ent;
- }
- if (strcasecmp(attrptr->attrname, _USER_NAME) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_user2ent;
- }
- user->name = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- (void) strcpy(user->name, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _USER_QUALIFIER) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- user->qualifier = nullstring;
- } else {
- user->qualifier = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- (void) strcpy(user->qualifier,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _USER_RES1) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- user->res1 = nullstring;
- } else {
- user->res1 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- (void) strcpy(user->res1,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _USER_RES2) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- user->res2 = nullstring;
- } else {
- user->res2 = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- (void) strcpy(user->res2,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- if (strcasecmp(attrptr->attrname, _USER_ATTRS) == 0) {
- if ((attrptr->attrvalue[0] == NULL) ||
- (len = strlen(attrptr->attrvalue[0])) < 1) {
- user->attr = nullstring;
- } else {
- user->attr = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_user2ent;
- }
- (void) strcpy(user->attr,
- attrptr->attrvalue[0]);
- }
- continue;
- }
- }
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getuserattr.c: _nss_ldap_user2ent]\n");
- (void) fprintf(stdout, " user-name: [%s]\n", user->name);
- if (user->qualifier != (char *)NULL) {
- (void) fprintf(stdout, " qualifier: [%s]\n",
- user->qualifier);
+ qu = __ns_ldap_getAttr(result->entry, _USER_QUALIFIER);
+ if (qu == NULL || qu[0] == NULL || (strlen(qu[0]) < 1))
+ qu_str = _NO_VALUE;
+ else
+ qu_str = qu[0];
+
+ res1 = __ns_ldap_getAttr(result->entry, _USER_RES2);
+ if (res1 == NULL || res1[0] == NULL || (strlen(res1[0]) < 1))
+ res1_str = _NO_VALUE;
+ else
+ res1_str = res1[0];
+
+ res2 = __ns_ldap_getAttr(result->entry, _USER_RES2);
+ if (res2 == NULL || res2[0] == NULL || (strlen(res2[0]) < 1))
+ res2_str = _NO_VALUE;
+ else
+ res2_str = res2[0];
+
+ attr = __ns_ldap_getAttr(result->entry, _USER_ATTRS);
+ if (attr == NULL || attr[0] == NULL || (strlen(attr[0]) < 1))
+ attr_str = _NO_VALUE;
+ else
+ attr_str = attr[0];
+ /* 5 = 4 ':' + 1 '\0' */
+ len = strlen(name[0]) + strlen(res1_str) + strlen(res2_str) +
+ strlen(qu_str) + strlen(attr_str) + 5;
+ if (len > buflen) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_user2str;
}
- if (user->res1 != (char *)NULL) {
- (void) fprintf(stdout, " res1: [%s]\n", user->res1);
- }
- if (user->res2 != (char *)NULL) {
- (void) fprintf(stdout, " res2: [%s]\n", user->res2);
- }
- if (user->attr != (char *)NULL) {
- (void) fprintf(stdout, " attr: [%s]\n", user->attr);
- }
-#endif /* DEBUG */
-result_user2ent:
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_user2str;
+ }
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+ (void) snprintf(buffer, len, "%s:%s:%s:%s:%s",
+ name[0], qu_str, res1_str, res2_str, attr_str);
+ /* The front end marshaller doesn't need the trailing null */
+ if (argp->buf.result != NULL)
+ be->buflen = strlen(be->buffer);
+
+result_user2str:
(void) __ns_ldap_freeResult(&be->result);
return ((int)nss_result);
}
@@ -207,10 +144,6 @@ getbyname(ldap_backend_ptr be, void *a)
char name[SEARCHFILTERLEN];
int ret;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[getuserattr.c: getbyname]\n");
-#endif /* DEBUG */
-
if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
return ((nss_status_t)NSS_NOTFOUND);
@@ -246,11 +179,7 @@ _nss_ldap_user_attr_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[getuserattr.c: _nss_ldap_user_attr_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(userattr_ops,
sizeof (userattr_ops)/sizeof (userattr_ops[0]), _USERATTR,
- user_attrs, _nss_ldap_user2ent));
+ user_attrs, _nss_ldap_user2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.c b/usr/src/lib/nsswitch/ldap/common/ldap_common.c
index 9d961d9d1d..a6537c7b41 100644
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.c
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.c
@@ -45,7 +45,8 @@
#define _F_GETGRENT "(objectClass=posixGroup)"
#define _F_GETHOSTENT "(objectClass=ipHost)"
#define _F_GETNETENT "(objectClass=ipNetwork)"
-#define _F_GETPROFNAME "(objectClass=SolarisProfAttr)"
+#define _F_GETPROFNAME \
+"(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
#define _F_GETPROTOENT "(objectClass=ipProtocol)"
#define _F_GETPWENT "(objectClass=posixAccount)"
#define _F_GETPRINTERENT "(objectClass=sunPrinter)"
@@ -85,7 +86,7 @@ static struct gettablefilter {
};
-nss_status_t
+static nss_status_t
switch_err(int rc, ns_ldap_error_t *error)
{
switch (rc) {
@@ -109,6 +110,7 @@ switch_err(int rc, ns_ldap_error_t *error)
return (NSS_UNAVAIL);
}
}
+/* ARGSUSED */
nss_status_t
_nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
char *database, char *searchfilter, char *domain,
@@ -136,16 +138,79 @@ _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
argp->returnval = 0;
rc = switch_err(rc, error);
(void) __ns_ldap_freeError(&error);
+
return (rc);
}
+ (void) __ns_ldap_freeError(&error);
/* callback function */
if ((callbackstat =
- be->ldapobj2ent(be, argp)) == NSS_STR_PARSE_SUCCESS) {
- argp->returnval = argp->buf.result;
- return ((nss_status_t)NSS_SUCCESS);
+ be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) {
+ goto error_out;
}
- (void) __ns_ldap_freeResult(&be->result);
+ /*
+ * publickey does not have a front end marshaller and expects
+ * a string to be returned in NSS.
+ * No need to convert file format -> struct.
+ *
+ */
+ if (be->db_type == NSS_LDAP_DB_PUBLICKEY) {
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ be->db_type = NSS_LDAP_DB_NONE;
+ return (NSS_SUCCESS);
+ }
+ /*
+ * Assume the switch engine wants the returned data in the file
+ * format when argp->buf.result == NULL.
+ * The front-end marshaller str2ether(ethers) uses
+ * ent (argp->buf.result) and buffer (argp->buf.buffer)
+ * for different purpose so ethers has to be treated differently.
+ */
+ if (argp->buf.result != NULL ||
+ be->db_type == NSS_LDAP_DB_ETHERS) {
+ /* file format -> struct */
+ if (argp->str2ent == NULL) {
+ callbackstat = NSS_STR_PARSE_PARSE;
+ goto error_out;
+ }
+
+ callbackstat = (*argp->str2ent)(be->buffer,
+ be->buflen,
+ argp->buf.result,
+ argp->buf.buffer,
+ argp->buf.buflen);
+ if (callbackstat == NSS_STR_PARSE_SUCCESS) {
+ if (be->db_type == NSS_LDAP_DB_ETHERS &&
+ argp->buf.buffer != NULL) {
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ } else {
+ argp->returnval = argp->buf.result;
+ argp->returnlen = 1; /* irrelevant */
+ }
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ be->db_type = NSS_LDAP_DB_NONE;
+ }
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+ } else {
+ /* return file format in argp->buf.buffer */
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+
+error_out:
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ be->db_type = NSS_LDAP_DB_NONE;
+ }
/* error */
if (callbackstat == NSS_STR_PARSE_PARSE) {
argp->returnval = 0;
@@ -163,12 +228,12 @@ _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
return ((nss_status_t)NSS_UNAVAIL);
}
-
/*
* This function is similar to _nss_ldap_lookup except it does not
* do a callback. It is only used by getnetgrent.c
*/
+/* ARGSUSED */
nss_status_t
_nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
char *database, char *searchfilter, char *domain,
@@ -227,6 +292,10 @@ _clean_ldap_backend(ldap_backend_ptr be)
free(be->toglue);
be->toglue = NULL;
}
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ }
free(be);
}
@@ -280,6 +349,7 @@ _nss_ldap_setent(ldap_backend_ptr be, void *a)
be->enumcookie = NULL;
be->result = NULL;
be->services_cookie = NULL;
+ be->buffer = NULL;
return ((nss_status_t)NSS_SUCCESS);
}
@@ -311,6 +381,10 @@ _nss_ldap_endent(ldap_backend_ptr be, void *a)
if (be->services_cookie != NULL) {
_nss_services_cookie_free((void **)&be->services_cookie);
}
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ }
return ((nss_status_t)NSS_SUCCESS);
}
@@ -353,11 +427,47 @@ next_entry:
(void) _nss_ldap_endent(be, a);
return (retcode);
} else {
- if ((parsestat = be->ldapobj2ent(be, argp))
+ /* ns_ldap_entry_t -> file format */
+ if ((parsestat = be->ldapobj2str(be, argp))
== NSS_STR_PARSE_SUCCESS) {
- be->result = NULL;
- argp->returnval = argp->buf.result;
- return ((nss_status_t)NSS_SUCCESS);
+ if (argp->buf.result != NULL) {
+ /* file format -> struct */
+ if (argp->str2ent == NULL) {
+ parsestat = NSS_STR_PARSE_PARSE;
+ goto error_out;
+ }
+ parsestat = (*argp->str2ent)(be->buffer,
+ be->buflen,
+ argp->buf.result,
+ argp->buf.buffer,
+ argp->buf.buflen);
+ if (parsestat == NSS_STR_PARSE_SUCCESS) {
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
+ be->result = NULL;
+ argp->returnval = argp->buf.result;
+ argp->returnlen = 1; /* irrevelant */
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+ } else {
+ /*
+ * nscd is not caching the enumerated
+ * entries. This code path would be dormant.
+ * Keep this path for the future references.
+ */
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen =
+ strlen(argp->buf.buffer) + 1;
+ }
+ }
+error_out:
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
}
be->result = NULL;
if (parsestat == NSS_STR_PARSE_PARSE) {
@@ -394,7 +504,7 @@ next_entry:
nss_backend_t *
_nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
- const char **attrs, fnf ldapobj2ent)
+ const char **attrs, fnf ldapobj2str)
{
ldap_backend_ptr be;
@@ -402,20 +512,13 @@ _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
#endif /* DEBUG */
- if ((be = (ldap_backend_ptr) malloc(sizeof (*be))) == 0)
+ if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0)
return (0);
be->ops = ops;
be->nops = (nss_dbop_t)nops;
be->tablename = (char *)strdup(tablename);
be->attrs = attrs;
- be->result = NULL;
- be->ldapobj2ent = ldapobj2ent;
- be->setcalled = 0;
- be->filter = NULL;
- be->enumcookie = NULL;
- be->netgroup_cookie = NULL;
- be->services_cookie = NULL;
- be->toglue = NULL;
+ be->ldapobj2str = ldapobj2str;
return ((nss_backend_t *)be);
}
@@ -436,8 +539,8 @@ chophostdomain(char *string, char *host, char *domain)
return (0);
}
*dot = '\0';
- strcpy(host, string);
- strcpy(domain, ++dot);
+ (void) strcpy(host, string);
+ (void) strcpy(domain, ++dot);
return (0);
}
diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.h b/usr/src/lib/nsswitch/ldap/common/ldap_common.h
index 23d5e2b1ae..deb5ffd642 100644
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.h
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.h
@@ -76,6 +76,19 @@ extern "C" {
((string != NULL) && (strchr(string, '.') != NULL))
#define SEARCHFILTERLEN 256
+#define _NO_VALUE ""
+
+#define TEST_AND_ADJUST(len, buffer, buflen, label) \
+ /* Use '>=' to ensure there is at least one byte left for '\0' */ \
+ if (len >= buflen || len < 0) { \
+ nss_result = NSS_STR_PARSE_ERANGE; \
+ goto label; \
+ } \
+ /* Adjust pointer and available buffer length */ \
+ buffer += len; \
+ buflen -= len;
+
+
/*
* Superset the nss_backend_t abstract data type. This ADT has
* been extended to include ldap associated data structures.
@@ -85,6 +98,12 @@ typedef struct ldap_backend *ldap_backend_ptr;
typedef nss_status_t (*ldap_backend_op_t)(ldap_backend_ptr, void *);
typedef int (*fnf)(ldap_backend_ptr be, nss_XbyY_args_t *argp);
+typedef enum {
+ NSS_LDAP_DB_NONE = 0,
+ NSS_LDAP_DB_PUBLICKEY = 1,
+ NSS_LDAP_DB_ETHERS = 2
+} nss_ldap_db_type_t;
+
struct ldap_backend {
ldap_backend_op_t *ops;
nss_dbop_t nops;
@@ -94,10 +113,13 @@ struct ldap_backend {
int setcalled;
const char **attrs;
ns_ldap_result_t *result;
- fnf ldapobj2ent;
+ fnf ldapobj2str;
void *netgroup_cookie;
void *services_cookie;
char *toglue;
+ char *buffer;
+ int buflen;
+ nss_ldap_db_type_t db_type;
};
extern nss_status_t _nss_ldap_destr(ldap_backend_ptr be, void *a);
@@ -105,7 +127,7 @@ extern nss_status_t _nss_ldap_endent(ldap_backend_ptr be, void *a);
extern nss_status_t _nss_ldap_setent(ldap_backend_ptr be, void *a);
extern nss_status_t _nss_ldap_getent(ldap_backend_ptr be, void *a);
nss_backend_t *_nss_ldap_constr(ldap_backend_op_t ops[], int nops,
- char *tablename, const char **attrs, fnf ldapobj2ent);
+ char *tablename, const char **attrs, fnf ldapobj2str);
extern nss_status_t _nss_ldap_nocb_lookup(ldap_backend_ptr be,
nss_XbyY_args_t *argp, char *database,
char *searchfilter, char *domain,
@@ -132,7 +154,6 @@ extern int _merge_SSD_filter(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata);
extern int _ldap_filter_name(char *filter_name, const char *name,
int filter_name_size);
-extern nss_status_t switch_err(int rc, ns_ldap_error_t *error);
extern void _nss_services_cookie_free(void **cookieP);
diff --git a/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c b/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c
index 90a21988a2..77e04f2cfe 100644
--- a/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c
+++ b/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c
@@ -45,82 +45,82 @@ static const char *tnrhdb_attrs[] = {
NULL
};
+static void
+escape_colon(char *in, char *out) {
+ int i, j;
+ for (i = 0, j = 0; in[i] != '\0'; i++) {
+ if (in[i] == ':') {
+ out[j++] = '\\';
+ out[j++] = in[i];
+ } else
+ out[j++] = in[i];
+ }
+ out[j] = '\0';
+}
+
+/*
+ * _nss_ldap_tnrhdb2str is the data marshaling method for the tnrhdb
+ * (tsol_getrhbyaddr()/tsol_getrhent()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into the file format.
+ *
+ * e.g.
+ *
+ * 192.168.120.6:public
+ * fec0\:\:a00\:20ff\:fea0\:21f7:cipso
+ *
+ */
static int
-_nss_ldap_tnrhdb2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_tnrhdb2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
+ int nss_result = NSS_STR_PARSE_SUCCESS;
int len = 0;
- int buflen = 0;
char *buffer = NULL;
- char *ceiling = NULL;
- ns_ldap_attr_t *attrptr;
+ char **addr, **template, *addr_out;
ns_ldap_result_t *result = be->result;
- tsol_rhstr_t *rhstrp;
+ char addr6[INET6_ADDRSTRLEN + 5]; /* 5 '\' for ':' at most */
+
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
- buffer = argp->buf.buffer;
- buflen = argp->buf.buflen;
- if (argp->buf.result == NULL) {
- nss_result = NSS_STR_PARSE_ERANGE;
- goto result_tnrhdb2ent;
+ addr = __ns_ldap_getAttr(result->entry, _TNRHDB_ADDR);
+ if (addr == NULL || addr[0] == NULL || (strlen(addr[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhdb2str;
}
- rhstrp = (tsol_rhstr_t *)(argp->buf.result);
- rhstrp->family = 0;
- rhstrp->address = rhstrp->template = NULL;
- ceiling = buffer + buflen;
- (void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
+
+ /*
+ * Escape ':' in IPV6.
+ * The value is stored in LDAP directory without escape charaters.
+ */
+ if (strchr(addr[0], ':') != NULL) {
+ escape_colon(addr[0], addr6);
+ addr_out = addr6;
+ } else
+ addr_out = addr[0];
+
+ template = __ns_ldap_getAttr(result->entry, _TNRHDB_TNAME);
+ if (template == NULL || template[0] == NULL ||
+ (strlen(template[0]) < 1)) {
nss_result = NSS_STR_PARSE_PARSE;
- goto result_tnrhdb2ent;
+ goto result_tnrhdb2str;
}
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
+ /* "addr:template" */
+ len = strlen(addr_out) + strlen(template[0]) + 2;
+
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
nss_result = NSS_STR_PARSE_PARSE;
- goto result_tnrhdb2ent;
- }
- if (strcasecmp(attrptr->attrname, _TNRHDB_ADDR) == 0) {
- len = strlen(attrptr->attrvalue[0]);
- if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_tnrhdb2ent;
- }
- rhstrp->address = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_tnrhdb2ent;
- }
- (void) strcpy(rhstrp->address, attrptr->attrvalue[0]);
- continue;
+ goto result_tnrhdb2str;
}
- if (strcasecmp(attrptr->attrname, _TNRHDB_TNAME) == 0) {
- len = strlen(attrptr->attrvalue[0]);
- if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
- nss_result = NSS_STR_PARSE_PARSE;
- goto result_tnrhdb2ent;
- }
- rhstrp->template = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_tnrhdb2ent;
- }
- (void) strcpy(rhstrp->template, attrptr->attrvalue[0]);
- continue;
- }
- }
- nss_result = NSS_STR_PARSE_SUCCESS;
+ be->buflen = len - 1;
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
-#ifdef DEBUG
- (void) printf("\n[tsol_getrhent.c: _nss_ldap_tnrhdb2ent]\n");
- (void) printf(" address: [%s]\n",
- rhstrp->address ? rhstrp->address : "NULL");
- (void) printf("template: [%s]\n",
- rhstrp->template ? rhstrp->template : "NULL");
-#endif /* DEBUG */
+ (void) snprintf(buffer, len, "%s:%s", addr_out, template[0]);
-result_tnrhdb2ent:
+result_tnrhdb2str:
(void) __ns_ldap_freeResult(&be->result);
return (nss_result);
}
@@ -132,23 +132,31 @@ getbyaddr(ldap_backend_ptr be, void *a)
char searchfilter[SEARCHFILTERLEN];
char userdata[SEARCHFILTERLEN];
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- struct in_addr addr;
- char buf[18];
- extern char *inet_ntoa_r();
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[tsol_getrhent.c: getbyaddr]\n");
-#endif /* DEBUG */
-
- (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
- (void) inet_ntoa_r(addr, buf);
+ if (argp->key.hostaddr.addr == NULL ||
+ (argp->key.hostaddr.type != AF_INET &&
+ argp->key.hostaddr.type != AF_INET6))
+ return (NSS_NOTFOUND);
+ if (strchr(argp->key.hostaddr.addr, ':') != NULL) {
+ /* IPV6 */
+ if (argp->key.hostaddr.type == AF_INET)
+ return (NSS_NOTFOUND);
+ } else {
+ /* IPV4 */
+ if (argp->key.hostaddr.type == AF_INET6)
+ return (NSS_NOTFOUND);
+ }
+ /*
+ * The IPV6 addresses are saved in the directory without '\'s.
+ * So don't need to escape colons in IPV6 addresses.
+ */
if (snprintf(searchfilter, sizeof (searchfilter), _F_GETTNDBBYADDR,
- buf) < 0)
+ argp->key.hostaddr.addr) < 0)
return ((nss_status_t)NSS_NOTFOUND);
if (snprintf(userdata, sizeof (userdata), _F_GETTNDBBYADDR_SSD,
- buf) < 0)
+ argp->key.hostaddr.addr) < 0)
return ((nss_status_t)NSS_NOTFOUND);
return (_nss_ldap_lookup(be, argp, _TNRHDB, searchfilter, NULL,
@@ -173,11 +181,7 @@ _nss_ldap_tnrhdb_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[tsol_getrhent.c: _nss_ldap_tnrhdb_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(tnrhdb_ops,
sizeof (tnrhdb_ops)/sizeof (tnrhdb_ops[0]), _TNRHDB,
- tnrhdb_attrs, _nss_ldap_tnrhdb2ent));
+ tnrhdb_attrs, _nss_ldap_tnrhdb2str));
}
diff --git a/usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c b/usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c
index b7f5423f6f..31c84df762 100644
--- a/usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c
+++ b/usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c
@@ -32,6 +32,7 @@
#define _TNRHTP_NAME "ipTnetTemplateName"
#define _TNRHTP_ATTRS "SolarisAttrKeyValue"
#define _F_GETTNTPBYNAME "(&(objectClass=ipTnetTemplate)"\
+ "(!(objectClass=ipTnetHost))" \
"(ipTnetTemplateName=%s))"
#define _F_GETTNTPBYNAME_SSD "(&(%%s)(ipTnetTemplateName=%s))"
@@ -41,97 +42,63 @@ static const char *tnrhtp_attrs[] = {
NULL
};
+/*
+ * _nss_ldap_tnrhtp2str is the data marshaling method for the tnrhtp
+ * (tsol_gettpbyaddr()/tsol_gettpent()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into the file format.
+ *
+ * e.g.
+ *
+ * admin_low:host_type=unlabeled;def_label=[0x0000000000000000000000000000000000
+ * 0000000000000000000000000000000000];min_sl=0x00000000000000000000000000000000
+ * 000000000000000000000000000000000000;max_sl=0x7ffffffffffffffffffffffffffffff
+ * fffffffffffffffffffffffffffffffffffff;doi=0;
+ */
static int
-_nss_ldap_tnrhtp2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+_nss_ldap_tnrhtp2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
{
- int i, nss_result;
+ int nss_result = NSS_STR_PARSE_SUCCESS;
int len = 0;
- int buflen = 0;
char *buffer = NULL;
- char *ceiling = NULL;
- ns_ldap_attr_t *attrptr;
+ char **attrs, **template;
ns_ldap_result_t *result = be->result;
- tsol_tpstr_t *tpstrp;
- buffer = argp->buf.buffer;
- buflen = argp->buf.buflen;
- if (argp->buf.result == NULL) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_tnrhtp2ent;
+ if (result == NULL)
+ return (NSS_STR_PARSE_PARSE);
+
+ template = __ns_ldap_getAttr(result->entry, _TNRHTP_NAME);
+ if (template == NULL || template[0] == NULL ||
+ (strlen(template[0]) < 1)) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2str;
}
- tpstrp = (tsol_tpstr_t *)(argp->buf.result);
- tpstrp->template = tpstrp->attrs = NULL;
- ceiling = buffer + buflen;
- (void) memset(argp->buf.buffer, 0, buflen);
- attrptr = getattr(result, 0);
- if (attrptr == NULL) {
+ attrs = __ns_ldap_getAttr(result->entry, _TNRHTP_ATTRS);
+ if (attrs == NULL || attrs[0] == NULL || (strlen(attrs[0]) < 1)) {
nss_result = NSS_STR_PARSE_PARSE;
- goto result_tnrhtp2ent;
+ goto result_tnrhtp2str;
}
- for (i = 0; i < result->entry->attr_count; i++) {
- attrptr = getattr(result, i);
- if (attrptr == NULL) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_tnrhtp2ent;
- }
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[tsol_gettpent.c: _nss_ldap_tnrhtp2ent %d]\n", i);
- (void) fprintf(stdout, " entry value count %d: %s:%s\n",
- attrptr->value_count,
- attrptr->attrname ? attrptr->attrname : "NULL",
- attrptr->attrvalue[0] ? attrptr->attrvalue[0] : "NULL");
-#endif /* DEBUG */
- if (strcasecmp(attrptr->attrname, _TNRHTP_NAME) == 0) {
- len = strlen(attrptr->attrvalue[0]);
- if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_tnrhtp2ent;
- }
- tpstrp->template = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_ERANGE;
- goto result_tnrhtp2ent;
- }
- (void) strcpy(tpstrp->template, attrptr->attrvalue[0]);
- continue;
- }
- if (strcasecmp(attrptr->attrname, _TNRHTP_ATTRS) == 0) {
- len = strlen(attrptr->attrvalue[0]);
- if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_tnrhtp2ent;
- }
- tpstrp->attrs = buffer;
- buffer += len + 1;
- if (buffer >= ceiling) {
- nss_result = (int)NSS_STR_PARSE_PARSE;
- goto result_tnrhtp2ent;
- }
- (void) strcpy(tpstrp->attrs, attrptr->attrvalue[0]);
- continue;
+
+ /* "template:attrs" */
+ len = strlen(template[0]) + strlen(attrs[0]) + 2;
+
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, len)) == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2str;
}
- }
- if (tpstrp->attrs == NULL)
- nss_result = NSS_STR_PARSE_PARSE;
- else
- nss_result = NSS_STR_PARSE_SUCCESS;
-
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[tsol_gettpent.c: _nss_ldap_tnrhtp2ent]\n");
- (void) fprintf(stdout, " template: [%s]\n",
- tpstrp->template ? tpstrp->template : "NULL");
- (void) fprintf(stdout, " attrs: [%s]\n",
- tpstrp->attrs ? tpstrp->attrs : "NULL");
-#endif /* DEBUG */
-
-result_tnrhtp2ent:
+ be->buflen = len - 1;
+ buffer = be->buffer;
+ } else
+ buffer = argp->buf.buffer;
+
+ (void) snprintf(buffer, len, "%s:%s", template[0], attrs[0]);
+
+result_tnrhtp2str:
(void) __ns_ldap_freeResult(&be->result);
return (nss_result);
}
-
static nss_status_t
getbyname(ldap_backend_ptr be, void *a)
{
@@ -139,9 +106,8 @@ getbyname(ldap_backend_ptr be, void *a)
char userdata[SEARCHFILTERLEN];
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
-#ifdef DEBUG
- (void) fprintf(stdout, "\n[tsol_gettpent.c: getbyname]\n");
-#endif /* DEBUG */
+ if (argp->key.name == NULL)
+ return (NSS_NOTFOUND);
if (snprintf(searchfilter, SEARCHFILTERLEN, _F_GETTNTPBYNAME,
argp->key.name) < 0)
@@ -164,7 +130,7 @@ static ldap_backend_op_t tnrhtp_ops[] = {
getbyname
};
-
+/* ARGSUSED */
nss_backend_t *
_nss_ldap_tnrhtp_constr(const char *dummy1,
const char *dummy2,
@@ -172,11 +138,7 @@ _nss_ldap_tnrhtp_constr(const char *dummy1,
const char *dummy4,
const char *dummy5)
{
-#ifdef DEBUG
- (void) fprintf(stdout,
- "\n[gettnrhtpattr.c: _nss_ldap_tnrhtp_constr]\n");
-#endif
return ((nss_backend_t *)_nss_ldap_constr(tnrhtp_ops,
sizeof (tnrhtp_ops)/sizeof (tnrhtp_ops[0]), _TNRHTP,
- tnrhtp_attrs, _nss_ldap_tnrhtp2ent));
+ tnrhtp_attrs, _nss_ldap_tnrhtp2str));
}
diff --git a/usr/src/lib/nsswitch/nis/Makefile.com b/usr/src/lib/nsswitch/nis/Makefile.com
index 63bd6a6936..2b0180d0d2 100644
--- a/usr/src/lib/nsswitch/nis/Makefile.com
+++ b/usr/src/lib/nsswitch/nis/Makefile.com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 1993,2001-2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -58,5 +57,8 @@ include ../../Makefile.com
# install this library in the root filesystem
include ../../../Makefile.rootfs
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+LINTFLAGS64 += -erroff=E_GLOBAL_COULD_BE_STATIC2
+
LDLIBS += -lnsl -lsocket
DYNLIB1 = nss_nis.so$(VERS)
diff --git a/usr/src/lib/nsswitch/nis/common/ether_addr.c b/usr/src/lib/nsswitch/nis/common/ether_addr.c
index 83d65a4bbb..fbd233a7c0 100644
--- a/usr/src/lib/nsswitch/nis/common/ether_addr.c
+++ b/usr/src/lib/nsswitch/nis/common/ether_addr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,10 @@
* CDDL HEADER END
*/
/*
- * nis/ether_addr.c -- "nis" backend for nsswitch "ethers" database
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * nis/ether_addr.c -- "nis" backend for nsswitch "ethers" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -51,7 +50,7 @@ getbyhost(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nis_lookup(be, argp, 0, "ethers.byname",
argp->key.name, 0));
@@ -62,11 +61,11 @@ getbyether(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char etherstr[18];
- u_char *e = argp->key.ether;
+ uchar_t *e = argp->key.ether;
- sprintf(etherstr, "%x:%x:%x:%x:%x:%x",
+ (void) snprintf(etherstr, 18, "%x:%x:%x:%x:%x:%x",
*e, *(e + 1), *(e + 2), *(e + 3), *(e + 4), *(e + 5));
return (_nss_nis_lookup(be, argp, 0, "ethers.byaddr", etherstr, 0));
}
diff --git a/usr/src/lib/nsswitch/nis/common/getauthattr.c b/usr/src/lib/nsswitch/nis/common/getauthattr.c
index c4040131f7..a37dcf00cd 100644
--- a/usr/src/lib/nsswitch/nis/common/getauthattr.c
+++ b/usr/src/lib/nsswitch/nis/common/getauthattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -49,6 +48,7 @@ static nis_backend_op_t authattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_auth_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nis/common/getauuser.c b/usr/src/lib/nsswitch/nis/common/getauuser.c
index 8abf038c7b..a86ba4112d 100644
--- a/usr/src/lib/nsswitch/nis/common/getauuser.c
+++ b/usr/src/lib/nsswitch/nis/common/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -50,6 +49,7 @@ static nis_backend_op_t auuser_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_audit_user_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nis/common/getexecattr.c b/usr/src/lib/nsswitch/nis/common/getexecattr.c
index bc912602bc..07f8640f0b 100644
--- a/usr/src/lib/nsswitch/nis/common/getexecattr.c
+++ b/usr/src/lib/nsswitch/nis/common/getexecattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,7 +40,7 @@ extern void massage_netdb(const char **, int *);
extern int _doexeclist(nss_XbyY_args_t *);
extern char *_exec_wild_id(char *, const char *);
extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
-
+extern char *_strtok_escape(char *, char *, char **);
typedef struct __exec_nis_args {
int *yp_status;
@@ -88,6 +87,43 @@ check_match(nss_XbyY_args_t *argp, int check_policy)
return (1);
}
+/*
+ * check_match_strbuf: set up the data needed by check_match()
+ * and call it to match exec_attr data in strbuf and argp->key.attrp
+ */
+static int
+check_match_strbuf(nss_XbyY_args_t *argp, char *strbuf, int check_policy)
+{
+ char *last = NULL;
+ char *sep = KV_TOKEN_DELIMIT;
+ execstr_t exec;
+ execstr_t *execp = &exec;
+ void *sp;
+ int rc;
+
+ /*
+ * Remove newline that yp_match puts at the
+ * end of the entry it retrieves from the map.
+ */
+ if (strbuf[argp->returnlen] == '\n') {
+ strbuf[argp->returnlen] = '\0';
+ }
+
+ execp->name = _strtok_escape(strbuf, sep, &last);
+ execp->policy = _strtok_escape(NULL, sep, &last);
+ execp->type = _strtok_escape(NULL, sep, &last);
+ execp->res1 = _strtok_escape(NULL, sep, &last);
+ execp->res2 = _strtok_escape(NULL, sep, &last);
+ execp->id = _strtok_escape(NULL, sep, &last);
+
+ sp = argp->returnval;
+ argp->returnval = execp;
+ rc = check_match(argp, check_policy);
+ argp->returnval = sp;
+ free(strbuf);
+
+ return (rc);
+}
static nss_status_t
_exec_nis_parse(const char *instr,
@@ -98,13 +134,28 @@ _exec_nis_parse(const char *instr,
int parse_stat;
nss_status_t res;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
+ char *strbuf;
+ int check_matched;
+ argp->returnval = NULL;
+ argp->returnlen = 0;
parse_stat = (*argp->str2ent)(instr, instr_len, argp->buf.result,
argp->buf.buffer, argp->buf.buflen);
switch (parse_stat) {
case NSS_STR_PARSE_SUCCESS:
- argp->returnval = argp->buf.result;
- if (check_match(argp, check_policy)) {
+ argp->returnlen = instr_len;
+ /* if exec_attr file format requested */
+ if (argp->buf.result == NULL) {
+ argp->returnval = argp->buf.buffer;
+ if ((strbuf = strdup(instr)) == NULL)
+ res = NSS_UNAVAIL;
+ check_matched = check_match_strbuf(argp,
+ strbuf, check_policy);
+ } else {
+ argp->returnval = argp->buf.result;
+ check_matched = check_match(argp, check_policy);
+ }
+ if (check_matched) {
res = NSS_SUCCESS;
if (_priv_exec->search_flag == GET_ALL) {
if (_doexeclist(argp) == 0) {
@@ -133,6 +184,7 @@ _exec_nis_parse(const char *instr,
* flow of key-value pairs. If it returns a non-zero value, it is not called
* again. The functional value of yp_all is then 0.
*/
+/*ARGSUSED*/
static int
_exec_nis_cb(int instatus,
char *inkey,
@@ -144,7 +196,6 @@ _exec_nis_cb(int instatus,
int check_policy = 1; /* always check policy for yp_all */
int stop_cb;
const char *filter;
- char *key = NULL;
nss_status_t res;
_exec_nis_args *eargp = (_exec_nis_args *)indata;
nss_XbyY_args_t *argp = eargp->argp;
@@ -206,7 +257,6 @@ _exec_nis_lookup(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
if (getby_flag == NSS_DBOP_EXECATTR_BYNAMEID) {
int check_policy = 0;
int vallen;
- int parse_stat;
char *val;
char key[MAX_INPUT];
@@ -330,6 +380,7 @@ getbyid(nis_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ /*LINTED*/
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYID);
@@ -348,6 +399,7 @@ getbynameid(nis_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ /*LINTED*/
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
@@ -371,6 +423,7 @@ static nis_backend_op_t execattr_ops[] = {
getbynameid
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_exec_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nis/common/getgrent.c b/usr/src/lib/nsswitch/nis/common/getgrent.c
index c1f529e70b..f6447a9d4c 100644
--- a/usr/src/lib/nsswitch/nis/common/getgrent.c
+++ b/usr/src/lib/nsswitch/nis/common/getgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,7 +58,7 @@ getbygid(be, a)
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char gidstr[12]; /* More than enough */
- sprintf(gidstr, "%d", argp->key.gid);
+ (void) snprintf(gidstr, 12, "%d", argp->key.gid);
return (_nss_nis_lookup(be, argp, 0, "group.bygid", gidstr, 0));
}
@@ -154,7 +153,6 @@ parse_netid(const char *buf, gid_t gid_array[], int maxgids, int *numgids_ptr)
{
int numgids = *numgids_ptr;
char *buf_next;
- int buflen = strlen(buf);
gid_t gid;
long value;
@@ -207,7 +205,6 @@ netid_lookup(struct nss_groupsbymem *argp)
nss_status_t res;
char *val;
int vallen;
- char *comment;
int parse_res;
char *lasts;
@@ -232,7 +229,7 @@ netid_lookup(struct nss_groupsbymem *argp)
return (res);
}
- strtok_r(val, "#", &lasts);
+ (void) strtok_r(val, "#", &lasts);
parse_res = parse_netid(val, argp->gid_array, argp->maxgids,
&argp->numgids);
diff --git a/usr/src/lib/nsswitch/nis/common/gethostent.c b/usr/src/lib/nsswitch/nis/common/gethostent.c
index 8636e5ef93..dd3f310336 100644
--- a/usr/src/lib/nsswitch/nis/common/gethostent.c
+++ b/usr/src/lib/nsswitch/nis/common/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* nis/gethostent.c -- "nis" backend for nsswitch "hosts" database
*/
@@ -43,7 +42,7 @@ getbyname(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
nss_status_t res;
const char *s;
@@ -82,7 +81,7 @@ getbyaddr(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
struct in_addr addr;
char buf[18];
nss_status_t res;
@@ -95,7 +94,7 @@ getbyaddr(be, a)
argp->key.hostaddr.len != sizeof (addr)) {
return (NSS_NOTFOUND);
}
- memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
res = _nss_nis_lookup(be, argp, 1, "hosts.byaddr",
inet_ntoa_r(addr, buf), 0);
if (res != NSS_SUCCESS)
diff --git a/usr/src/lib/nsswitch/nis/common/gethostent6.c b/usr/src/lib/nsswitch/nis/common/gethostent6.c
index 4f1da89d04..48fb1f6377 100644
--- a/usr/src/lib/nsswitch/nis/common/gethostent6.c
+++ b/usr/src/lib/nsswitch/nis/common/gethostent6.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1988-1992, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* nis/gethostent.c -- "nis" backend for nsswitch "ipnodes" database
@@ -94,7 +93,7 @@ getbyaddr(be, a)
argp->key.hostaddr.len != sizeof (addr)) {
return (NSS_NOTFOUND);
}
- memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
if (IN6_IS_ADDR_V4MAPPED(&addr)) {
if (inet_ntop(AF_INET, (void *) &addr.s6_addr[12],
(void *)buf, INET_ADDRSTRLEN) == NULL) {
diff --git a/usr/src/lib/nsswitch/nis/common/getnetgrent.c b/usr/src/lib/nsswitch/nis/common/getnetgrent.c
index 4863f8fdff..92a631421f 100644
--- a/usr/src/lib/nsswitch/nis/common/getnetgrent.c
+++ b/usr/src/lib/nsswitch/nis/common/getnetgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -100,7 +99,7 @@ getnetgr_get(be, a)
struct nis_getnetgr_be *be;
void *a;
{
- struct nss_getnetgrent_args *args = (struct nss_getnetgrent_args *) a;
+ struct nss_getnetgrent_args *args = (struct nss_getnetgrent_args *)a;
struct grouplist *mem;
if ((mem = be->next_member) == 0) {
@@ -120,7 +119,7 @@ getnetgr_get(be, a)
args->retp[i] = 0;
} else if ((len = strlen(str) + 1) <= buflen) {
args->retp[i] = buffer;
- memcpy(buffer, str, len);
+ (void) memcpy(buffer, str, len);
buffer += len;
buflen -= len;
} else {
@@ -170,7 +169,7 @@ getnetgr_destr(be, dummy)
void *dummy;
{
if (be != 0) {
- getnetgr_end(be, (void *)0);
+ (void) getnetgr_end(be, (void *)0);
free(be);
}
return (NSS_SUCCESS);
@@ -248,7 +247,7 @@ static void
ngt_init(ngt)
struct netgrtab *ngt;
{
- memset((void *)ngt, 0, sizeof (*ngt));
+ (void) memset((void *)ngt, 0, sizeof (*ngt));
ngt->expand_lastp = &ngt->expand_first;
}
@@ -285,7 +284,7 @@ ngt_insert(ngt, name, namelen)
if (cur == 0) {
return; /* Out of memory, too bad */
}
- memcpy(cur->name, name, namelen);
+ (void) memcpy(cur->name, name, namelen);
cur->name[namelen] = 0;
/* Insert in hash table */
@@ -349,7 +348,7 @@ top_down(struct nis_netgr_be *be, const char **groups, int ngroups,
int done;
nss_status_t result;
- if ((ngt = (struct netgrtab *) malloc(sizeof (*ngt))) == 0) {
+ if ((ngt = (struct netgrtab *)malloc(sizeof (*ngt))) == 0) {
return (NSS_UNAVAIL);
}
ngt_init(ngt);
@@ -373,7 +372,9 @@ top_down(struct nis_netgr_be *be, const char **groups, int ngroups,
result = _nss_nis_ypmatch(be->domain, "netgroup", group,
&val, &vallen, &yperr);
if (result != NSS_SUCCESS) {
+ /*LINTED E_NOP_IF_STMT*/
if (result == NSS_NOTFOUND) {
+ ;
#ifdef DEBUG
syslog(LOG_WARNING,
"NIS netgroup lookup: %s doesn't exist",
@@ -550,11 +551,11 @@ netgr_set(be, a)
struct nis_netgr_be *be;
void *a;
{
- struct nss_setnetgrent_args *args = (struct nss_setnetgrent_args *) a;
+ struct nss_setnetgrent_args *args = (struct nss_setnetgrent_args *)a;
struct nis_getnetgr_be *get_be;
nss_status_t res;
- get_be = (struct nis_getnetgr_be *) malloc(sizeof (*get_be));
+ get_be = (struct nis_getnetgr_be *)malloc(sizeof (*get_be));
if (get_be == 0) {
return (NSS_UNAVAIL);
}
@@ -570,7 +571,7 @@ netgr_set(be, a)
get_be->netgroup = strdup(args->netgroup);
get_be->next_member = get_be->all_members;
- args->iterator = (nss_backend_t *) get_be;
+ args->iterator = (nss_backend_t *)get_be;
} else {
args->iterator = 0;
free(get_be);
@@ -815,7 +816,7 @@ netgr_in(be, a)
struct nis_netgr_be *be;
void *a;
{
- struct nss_innetgr_args *ia = (struct nss_innetgr_args *) a;
+ struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a;
nss_status_t res;
ia->status = NSS_NETGR_NO;
@@ -852,7 +853,7 @@ netgr_in(be, a)
*/
/*ARGSUSED*/
-nss_status_t
+static nss_status_t
netgr_destr(be, dummy)
struct nis_netgr_be *be;
void *dummy;
@@ -882,12 +883,12 @@ _nss_nis_netgroup_constr(dummy1, dummy2, dummy3)
struct nis_netgr_be *be;
if ((domain = _nss_nis_domain()) == 0 ||
- (be = (struct nis_netgr_be *) malloc(sizeof (*be))) == 0) {
+ (be = (struct nis_netgr_be *)malloc(sizeof (*be))) == 0) {
return (0);
}
be->ops = netgroup_ops;
be->n_ops = sizeof (netgroup_ops) / sizeof (netgroup_ops[0]);
be->domain = domain;
- return ((nss_backend_t *) be);
+ return ((nss_backend_t *)be);
}
diff --git a/usr/src/lib/nsswitch/nis/common/getprinter.c b/usr/src/lib/nsswitch/nis/common/getprinter.c
index 0ccb484541..2983a00078 100644
--- a/usr/src/lib/nsswitch/nis/common/getprinter.c
+++ b/usr/src/lib/nsswitch/nis/common/getprinter.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,7 +36,6 @@ getbyname(be, a)
void *a;
{
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- nss_status_t res;
return (_nss_nis_lookup(be, argp, 0, "printers.conf.byname",
argp->key.name, 0));
@@ -51,6 +49,7 @@ static nis_backend_op_t printers_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_printers_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
diff --git a/usr/src/lib/nsswitch/nis/common/getprofattr.c b/usr/src/lib/nsswitch/nis/common/getprofattr.c
index 9813f70054..cdf4793e4c 100644
--- a/usr/src/lib/nsswitch/nis/common/getprofattr.c
+++ b/usr/src/lib/nsswitch/nis/common/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -49,6 +48,7 @@ static nis_backend_op_t profattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_prof_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nis/common/getprojent.c b/usr/src/lib/nsswitch/nis/common/getprojent.c
index 10b43d243f..c388f65749 100644
--- a/usr/src/lib/nsswitch/nis/common/getprojent.c
+++ b/usr/src/lib/nsswitch/nis/common/getprojent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -42,7 +41,7 @@ static nss_status_t
getbyid(nis_backend_ptr_t be, void *a) {
char projstr[PROJNAME_MAX];
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- (void) sprintf(projstr, "%d", argp->key.projid);
+ (void) snprintf(projstr, PROJNAME_MAX, "%ld", argp->key.projid);
return (_nss_nis_lookup(be, argp, 0, "project.byprojid", projstr, 0));
}
diff --git a/usr/src/lib/nsswitch/nis/common/getpwnam.c b/usr/src/lib/nsswitch/nis/common/getpwnam.c
index d623ebcbbd..a23ee8af5c 100644
--- a/usr/src/lib/nsswitch/nis/common/getpwnam.c
+++ b/usr/src/lib/nsswitch/nis/common/getpwnam.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* nis/getpwnam.c -- "nis" backend for nsswitch "passwd" database
*/
@@ -36,7 +35,7 @@ getbyname(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nis_lookup(be, argp, 0,
"passwd.byname", argp->key.name, 0));
@@ -47,10 +46,10 @@ getbyuid(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char uidstr[12]; /* More than enough */
- sprintf(uidstr, "%d", argp->key.uid);
+ (void) snprintf(uidstr, 12, "%ld", argp->key.uid);
return (_nss_nis_lookup(be, argp, 0, "passwd.byuid", uidstr, 0));
}
diff --git a/usr/src/lib/nsswitch/nis/common/getrpcent.c b/usr/src/lib/nsswitch/nis/common/getrpcent.c
index 88794e19a6..a2ead8d1e9 100644
--- a/usr/src/lib/nsswitch/nis/common/getrpcent.c
+++ b/usr/src/lib/nsswitch/nis/common/getrpcent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* nis/getrpcent.c -- "nis" backend for nsswitch "rpc" database
*/
@@ -41,19 +40,29 @@ static int
check_name(args)
nss_XbyY_args_t *args;
{
- struct rpcent *rpc = (struct rpcent *) args->returnval;
+ struct rpcent *rpc = (struct rpcent *)args->returnval;
const char *name = args->key.name;
char **aliasp;
- if (strcmp(rpc->r_name, name) == 0) {
- return (1);
- }
- for (aliasp = rpc->r_aliases; *aliasp != 0; aliasp++) {
- if (strcmp(*aliasp, name) == 0) {
+ if (rpc) {
+ if (strcmp(rpc->r_name, name) == 0) {
return (1);
}
+ for (aliasp = rpc->r_aliases; *aliasp != 0; aliasp++) {
+ if (strcmp(*aliasp, name) == 0) {
+ return (1);
+ }
+ }
+ return (0);
+ } else {
+ /*
+ * NSS2: nscd is running.
+ */
+ return (_nss_nis_check_name_aliases(args,
+ (const char *)args->buf.buffer,
+ strlen(args->buf.buffer)));
+
}
- return (0);
}
static mutex_t no_byname_lock = DEFAULTMUTEX;
@@ -64,30 +73,31 @@ getbyname(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
int no_map;
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
(void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
(void) _mutex_lock(&no_byname_lock);
no_map = no_byname_map;
(void) _mutex_unlock(&no_byname_lock);
- (void) _thr_sigsetmask(SIG_SETMASK, &oldmask, (sigset_t*)NULL);
+ (void) _thr_sigsetmask(SIG_SETMASK, &oldmask, (sigset_t *)NULL);
if (no_map == 0) {
int yp_status;
nss_status_t res;
res = _nss_nis_lookup(be, argp, 1, "rpc.byname",
- argp->key.name, &yp_status);
+ argp->key.name, &yp_status);
if (yp_status == YPERR_MAP) {
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&no_byname_lock);
no_byname_map = 1;
_mutex_unlock(&no_byname_lock);
- _thr_sigsetmask(SIG_SETMASK, &oldmask, (sigset_t*)NULL);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask,
+ (sigset_t *)NULL);
} else /* if (res == NSS_SUCCESS) <==== */ {
return (res);
}
@@ -101,10 +111,10 @@ getbynumber(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char numstr[12];
- sprintf(numstr, "%d", argp->key.number);
+ (void) sprintf(numstr, "%d", argp->key.number);
return (_nss_nis_lookup(be, argp, 1, "rpc.bynumber", numstr, 0));
}
diff --git a/usr/src/lib/nsswitch/nis/common/getservent.c b/usr/src/lib/nsswitch/nis/common/getservent.c
index 373ca89391..13b0ea17ea 100644
--- a/usr/src/lib/nsswitch/nis/common/getservent.c
+++ b/usr/src/lib/nsswitch/nis/common/getservent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* nis/getservent.c -- "nis" backend for nsswitch "services" database
*/
@@ -30,11 +29,13 @@
#include "nis_common.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <malloc.h>
#include <netdb.h>
#include <synch.h>
+#include <ctype.h>
#include <rpcsvc/ypclnt.h>
#include <thread.h>
#include <sys/types.h>
@@ -44,7 +45,7 @@ static int
check_name(args)
nss_XbyY_args_t *args;
{
- struct servent *serv = (struct servent *) args->returnval;
+ struct servent *serv = (struct servent *)args->returnval;
const char *name = args->key.serv.serv.name;
const char *proto = args->key.serv.proto;
char **aliasp;
@@ -63,6 +64,84 @@ check_name(args)
return (0);
}
+static int
+check_name2(nss_XbyY_args_t *argp)
+{
+ const char *limit, *linep, *keyp;
+ int name_match = 0;
+
+ linep = (const char *)argp->buf.buffer;
+ limit = linep + strlen(argp->buf.buffer);
+ keyp = argp->key.serv.serv.name;
+
+ /* compare name */
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && linep < limit && isspace(*linep)) {
+ if (argp->key.serv.proto == NULL)
+ return (1);
+ else
+ name_match = 1;
+ }
+
+ /* skip remainder of the name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* skip port number */
+ while (linep < limit && !isspace(*linep) && *linep != '/')
+ linep++;
+ if (linep == limit || *linep != '/')
+ return (0);
+
+ linep++;
+ if ((keyp = argp->key.serv.proto) == NULL) {
+ /* skip protocol */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ } else {
+ /* compare protocol */
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ /* no protocol match */
+ if (*keyp || (linep < limit && !isspace(*linep)))
+ return (0);
+ /* protocol and name match, return */
+ if (name_match)
+ return (1);
+ /* protocol match but name yet to be matched, so continue */
+ }
+
+ /* compare with the aliases */
+ while (linep < limit) {
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* compare with the alias name */
+ keyp = argp->key.serv.serv.name;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && (linep == limit || isspace(*linep)))
+ return (1);
+
+ /* skip remainder of the alias name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ }
+ return (0);
+}
+
static mutex_t no_byname_lock = DEFAULTMUTEX;
static int no_byname_map = 0;
@@ -71,13 +150,13 @@ getbyname(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
const char *name = argp->key.serv.serv.name;
const char *proto = argp->key.serv.proto;
int no_map;
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
(void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
(void) _mutex_lock(&no_byname_lock);
no_map = no_byname_map;
@@ -92,37 +171,46 @@ getbyname(be, a)
res = _nss_nis_lookup(be, argp, 1,
"services.byservicename", name, &yp_status);
} else {
- char *key = malloc(strlen(name) + strlen(proto) + 3);
+ int len = strlen(name) + strlen(proto) + 3;
+ char *key = malloc(len);
- if (key == 0) {
+ if (key == NULL) {
return (NSS_UNAVAIL);
}
- sprintf(key, "%s/%s", name, proto);
+ (void) snprintf(key, len, "%s/%s", name, proto);
res = _nss_nis_lookup(be, argp, 1,
"services.byservicename", key, &yp_status);
free(key);
}
if (yp_status == YPERR_MAP) {
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&no_byname_lock);
no_byname_map = 1;
_mutex_unlock(&no_byname_lock);
- _thr_sigsetmask(SIG_SETMASK, &oldmask, (sigset_t*)NULL);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask,
+ (sigset_t *)NULL);
} else /* if (res == NSS_SUCCESS) <==== */ {
return (res);
}
}
- return (_nss_nis_XY_all(be, argp, 1, name, check_name));
+ /*
+ * use check_anme to compare service name if nss1 or nss2 and
+ * request is not from nscd; otherwise use check_name2
+ */
+ if (argp->buf.result != NULL)
+ return (_nss_nis_XY_all(be, argp, 1, name, check_name));
+ else
+ return (_nss_nis_XY_all(be, argp, 1, name, check_name2));
}
static int
check_port(args)
nss_XbyY_args_t *args;
{
- struct servent *serv = (struct servent *) args->returnval;
+ struct servent *serv = (struct servent *)args->returnval;
/*
* We only resorted to _nss_nis_XY_all because proto == 0, so just...
@@ -130,28 +218,87 @@ check_port(args)
return (serv->s_port == args->key.serv.serv.port);
}
+static int
+check_port2(nss_XbyY_args_t *argp)
+{
+ const char *limit, *linep, *keyp, *numstart;
+ int numlen, s_port;
+ char numbuf[12], *numend;
+
+ linep = (const char *)argp->buf.buffer;
+ limit = linep + strlen(argp->buf.buffer);
+
+ /* skip name */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+
+ /* compare port num */
+ numstart = linep;
+ while (linep < limit && !isspace(*linep) && *linep != '/')
+ linep++;
+ if (linep == limit || *linep != '/')
+ return (0);
+ numlen = linep - numstart;
+ if (numlen == 0 || numlen >= sizeof (numbuf))
+ return (0);
+ (void) memcpy(numbuf, numstart, numlen);
+ numbuf[numlen] = '\0';
+ s_port = htons((int)strtol(numbuf, &numend, 10));
+ if (*numend != '\0')
+ return (0);
+ if (s_port == argp->key.serv.serv.port) {
+ if ((keyp = argp->key.serv.proto) == NULL)
+ return (1);
+ } else
+ return (0);
+
+ /* compare protocol */
+ linep++;
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ return (*keyp == '\0' && (linep == limit || isspace(*linep)));
+}
+
+
static nss_status_t
getbyport(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
int port = ntohs(argp->key.serv.serv.port);
const char *proto = argp->key.serv.proto;
char *key;
nss_status_t res;
+ int len;
if (proto == 0) {
char portstr[12];
- sprintf(portstr, "%d", port);
- return (_nss_nis_XY_all(be, argp, 1, portstr, check_port));
+ (void) snprintf(portstr, 12, "%d", port);
+ /*
+ * use check_port to compare service port if nss1 or
+ * nss2 and request is not from nscd; otherwise use
+ * check_port2
+ */
+ if (argp->buf.result != NULL)
+ return (_nss_nis_XY_all(be, argp, 1, portstr,
+ check_port));
+ else
+ return (_nss_nis_XY_all(be, argp, 1, portstr,
+ check_port2));
}
- if ((key = malloc(strlen(proto) + 14)) == 0) {
+ len = strlen(proto) + 14;
+ if ((key = malloc(len)) == 0) {
return (NSS_UNAVAIL);
}
- sprintf(key, "%d/%s", port, proto);
+ (void) snprintf(key, len, "%d/%s", port, proto);
res = _nss_nis_lookup(be, argp, 1, "services.byname", key, 0);
diff --git a/usr/src/lib/nsswitch/nis/common/getspent.c b/usr/src/lib/nsswitch/nis/common/getspent.c
index 060083f0b9..55aff0b42f 100644
--- a/usr/src/lib/nsswitch/nis/common/getspent.c
+++ b/usr/src/lib/nsswitch/nis/common/getspent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,10 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* nis/getspent.c -- "nis" backend for nsswitch "shadow" database
*/
@@ -54,7 +54,7 @@ nis_str2spent(instr, lenstr, ent, buffer, buflen)
int buflen;
{
struct spwd *spwd = (struct spwd *)ent;
- char *p, *q;
+ char *p, *q, *r;
/*
* We know that instr != 0 because we're in 'nis', not 'files'
@@ -70,19 +70,34 @@ nis_str2spent(instr, lenstr, ent, buffer, buflen)
if (q + 1 - instr > buflen) {
return (NSS_STR_PARSE_ERANGE);
}
- memcpy(buffer, instr, q - instr);
- buffer[p - instr] = '\0';
- buffer[q - instr] = '\0';
-
- spwd->sp_namp = buffer;
- spwd->sp_pwdp = buffer + (p + 1 - instr);
- spwd->sp_lstchg = -1;
- spwd->sp_min = -1;
- spwd->sp_max = -1;
- spwd->sp_warn = -1;
- spwd->sp_inact = -1;
- spwd->sp_expire = -1;
- spwd->sp_flag = 0;
+ /*
+ * "name:password" is copied
+ */
+ (void) memcpy(buffer, instr, q - instr);
+ if (spwd) {
+ buffer[p - instr] = '\0';
+ buffer[q - instr] = '\0';
+
+ spwd->sp_namp = buffer;
+ spwd->sp_pwdp = buffer + (p + 1 - instr);
+ spwd->sp_lstchg = -1;
+ spwd->sp_min = -1;
+ spwd->sp_max = -1;
+ spwd->sp_warn = -1;
+ spwd->sp_inact = -1;
+ spwd->sp_expire = -1;
+ spwd->sp_flag = 0;
+ } else {
+ /*
+ * NSS2: nscd is running. Return files format.
+ *
+ * name:password:::::::
+ */
+ r = buffer + (q - instr);
+ *r = '\0';
+ if (strlcat(buffer, ":::::::", buflen) >= buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ }
return (NSS_STR_PARSE_SUCCESS);
}
@@ -93,10 +108,11 @@ getbyname(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
cstr2ent_t save_c2e;
nss_status_t res;
struct spwd *spwd;
+ char *p;
save_c2e = argp->str2ent;
argp->str2ent = nis_str2spent;
@@ -110,12 +126,32 @@ getbyname(be, a)
* succeed if the caller's uid is 0 because only root user
* can use privilege port.
*/
- if ((res == NSS_SUCCESS) && (spwd->sp_pwdp) &&
- (*(spwd->sp_pwdp) == '#') && (*(spwd->sp_pwdp + 1) == '#')) {
- /* get password from passwd.adjunct.byname */
- res = _nss_nis_lookup_rsvdport(be, argp, 0,
+ if (res == NSS_SUCCESS) {
+ if (spwd) {
+ if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') &&
+ (*(spwd->sp_pwdp + 1) == '#')) {
+ /* get password from passwd.adjunct.byname */
+ res = _nss_nis_lookup_rsvdport(be, argp, 0,
"passwd.adjunct.byname",
argp->key.name, 0);
+ }
+ } else {
+ /*
+ * getent request from nscd
+ */
+ if ((p = memchr(argp->buf.buffer, ':',
+ argp->buf.buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ if (strncmp(p + 1, "##", 2) == 0)
+ /* get password from passwd.adjunct.byname */
+ res = _nss_nis_lookup_rsvdport(be, argp, 0,
+ "passwd.adjunct.byname",
+ argp->key.name, 0);
+ if (res == NSS_SUCCESS) {
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ }
+ }
}
argp->str2ent = save_c2e;
@@ -131,10 +167,11 @@ getent(be, a)
nis_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
cstr2ent_t save_c2e;
nss_status_t res;
struct spwd *spwd;
+ char *p;
save_c2e = argp->str2ent;
argp->str2ent = nis_str2spent;
@@ -148,13 +185,36 @@ getent(be, a)
* succeed if the caller's uid is 0 because only root user
* can use privilege port.
*/
- if ((res == NSS_SUCCESS) && (spwd->sp_pwdp) &&
- (*(spwd->sp_pwdp) == '#') && (*(spwd->sp_pwdp + 1) == '#')) {
- /* get password from passwd.adjunct.byname */
- res = _nss_nis_lookup_rsvdport(be, argp, 0,
+ if (res == NSS_SUCCESS) {
+ if (spwd) {
+ if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') &&
+ (*(spwd->sp_pwdp + 1) == '#')) {
+ /* get password from passwd.adjunct.byname */
+ res = _nss_nis_lookup_rsvdport(be, argp, 0,
"passwd.adjunct.byname",
spwd->sp_namp, 0);
+ }
+ } else {
+ /*
+ * getent request from nscd
+ */
+ if ((p = memchr(argp->buf.buffer, ':',
+ argp->buf.buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ if (strncmp(p + 1, "##", 2) == 0) {
+ /* need the name for the next search */
+ *p = '\0';
+ /* get password from passwd.adjunct.byname */
+ res = _nss_nis_lookup_rsvdport(be, argp, 0,
+ "passwd.adjunct.byname", p, 0);
+ }
+ if (res == NSS_SUCCESS) {
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
+ }
+ }
}
+
argp->str2ent = save_c2e;
return (res);
}
@@ -173,6 +233,7 @@ static nis_backend_op_t shadow_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_shadow_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
diff --git a/usr/src/lib/nsswitch/nis/common/getuserattr.c b/usr/src/lib/nsswitch/nis/common/getuserattr.c
index c3550c51ba..48e961550b 100644
--- a/usr/src/lib/nsswitch/nis/common/getuserattr.c
+++ b/usr/src/lib/nsswitch/nis/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -49,6 +48,7 @@ static nis_backend_op_t userattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nis_user_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nis/common/nis_common.c b/usr/src/lib/nsswitch/nis/common/nis_common.c
index e7e90db51f..e90d82eb13 100644
--- a/usr/src/lib/nsswitch/nis/common/nis_common.c
+++ b/usr/src/lib/nsswitch/nis/common/nis_common.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,10 +70,12 @@ switch_err(ypstatus, ismatch)
{
switch (ypstatus) {
case 0:
+ errno = 0;
return (NSS_SUCCESS);
case YPERR_BADARGS:
case YPERR_KEY:
+ errno = 0;
return (NSS_NOTFOUND);
/*
@@ -161,7 +162,7 @@ _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp)
#if MT_UNSAFE_YP
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&one_lane);
#endif
@@ -182,7 +183,8 @@ _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp)
* XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct)
* lookups when we need a reserved port.
*/
-nss_status_t
+
+static nss_status_t
_nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp)
const char *domain;
const char *map;
@@ -192,12 +194,11 @@ _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp)
int *ypstatusp;
{
int ypstatus;
- extern int yp_match_rsvdport();
#if MT_UNSAFE_YP
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&one_lane);
#endif
@@ -240,10 +241,13 @@ _nss_nis_lookup(be, args, netdb, map, key, ypstatusp)
massage_netdb((const char **)&val, &vallen);
}
+ args->returnval = NULL;
+ args->returnlen = 0;
parsestat = (*args->str2ent)(val, vallen,
args->buf.result, args->buf.buffer, args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = args->buf.result;
+ args->returnlen = vallen;
res = NSS_SUCCESS;
} else if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
@@ -282,10 +286,13 @@ _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp)
massage_netdb((const char **)&val, &vallen);
}
+ args->returnval = NULL;
+ args->returnlen = 0;
parsestat = (*args->str2ent)(val, vallen,
args->buf.result, args->buf.buffer, args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = args->buf.result;
+ args->returnlen = vallen;
res = NSS_SUCCESS;
} else if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
@@ -314,7 +321,7 @@ do_getent(be, args, netdb)
#if MT_UNSAFE_YP
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&one_lane);
#endif
@@ -345,10 +352,13 @@ do_getent(be, args, netdb)
massage_netdb((const char **)&outval, &outvallen);
}
+ args->returnval = NULL;
+ args->returnlen = 0;
parsestat = (*args->str2ent)(outval, outvallen,
args->buf.result, args->buf.buffer, args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = args->buf.result;
+ args->returnlen = outvallen;
res = NSS_SUCCESS;
} else if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
@@ -450,7 +460,7 @@ _nss_nis_do_all(be, args, filter, func)
#if MT_UNSAFE_YP
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
_mutex_lock(&one_lane);
#endif
@@ -494,12 +504,15 @@ XbyY_iterator(instr, instr_len, a)
massage_netdb(&instr, &instr_len);
}
+ args->returnval = NULL;
+ args->returnlen = 0;
parsestat = (*args->str2ent)(instr, instr_len,
args->buf.result, args->buf.buffer, args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = args->buf.result;
if ((*xydata->func)(args)) {
res = NSS_SUCCESS;
+ args->returnlen = instr_len;
} else {
res = NSS_NOTFOUND;
args->returnval = 0;
@@ -545,7 +558,7 @@ _nss_nis_destr(be, dummy)
{
if (be != 0) {
/* === Should change to invoke ops[ENDENT] ? */
- _nss_nis_endent(be, 0);
+ (void) _nss_nis_endent(be, 0);
free(be);
}
return (NSS_SUCCESS); /* In case anyone is dumb enough to check */
@@ -565,7 +578,7 @@ _nss_nis_domain()
*/
sigset_t oldmask, newmask;
- sigfillset(&newmask);
+ (void) sigfillset(&newmask);
(void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
(void) _mutex_lock(&yp_domain_lock);
@@ -609,3 +622,57 @@ _nss_nis_constr(ops, n_ops, enum_map)
return ((nss_backend_t *)be);
}
+
+/*
+ * This routine is used to parse lines of the form:
+ * name number aliases
+ * It returns 1 if the key in argp matches any one of the
+ * names in the line, otherwise 0
+ * Used by rpc
+ */
+int
+_nss_nis_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
+ int linelen)
+{
+ const char *limit, *linep, *keyp;
+
+ linep = line;
+ limit = line + linelen;
+ keyp = argp->key.name;
+
+ /* compare name */
+ while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && linep < limit && isspace(*linep))
+ return (1);
+ /* skip remainder of the name, if any */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* compare with the aliases */
+ while (linep < limit) {
+ /*
+ * 1st pass: skip number
+ * Other passes: skip remainder of the alias name, if any
+ */
+ while (linep < limit && !isspace(*linep))
+ linep++;
+ /* skip the delimiting spaces */
+ while (linep < limit && isspace(*linep))
+ linep++;
+ /* compare with the alias name */
+ keyp = argp->key.name;
+ while (*keyp && linep < limit && !isspace(*linep) &&
+ *keyp == *linep) {
+ keyp++;
+ linep++;
+ }
+ if (*keyp == '\0' && (linep == limit || isspace(*linep)))
+ return (1);
+ }
+ return (0);
+}
diff --git a/usr/src/lib/nsswitch/nis/common/nis_common.h b/usr/src/lib/nsswitch/nis/common/nis_common.h
index 281f80cb91..ad5407700e 100644
--- a/usr/src/lib/nsswitch/nis/common/nis_common.h
+++ b/usr/src/lib/nsswitch/nis/common/nis_common.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -116,6 +115,9 @@ extern int __nss2herrno(nss_status_t nsstat);
extern int _thr_sigsetmask(int how, const sigset_t *set, sigset_t *oset);
extern int _mutex_lock(mutex_t *mp);
extern int _mutex_unlock(mutex_t *mp);
+extern int _nss_nis_check_name_aliases(nss_XbyY_args_t *argp,
+ const char *line,
+ int linelen);
/* private yp "configurable lookup persistence" interface in libnsl */
extern int __yp_match_cflookup(char *, char *, char *, int, char **,
diff --git a/usr/src/lib/nsswitch/nisplus/Makefile.com b/usr/src/lib/nsswitch/nisplus/Makefile.com
index b060f52c50..c7481d2fe3 100644
--- a/usr/src/lib/nsswitch/nisplus/Makefile.com
+++ b/usr/src/lib/nsswitch/nisplus/Makefile.com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 1993,2001-2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -57,5 +56,8 @@ include ../../Makefile.com
# install this library in the root filesystem
include ../../../Makefile.rootfs
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2
+LINTFLAGS64 += -erroff=E_GLOBAL_COULD_BE_STATIC2
+
LDLIBS += -lnsl -lsocket
DYNLIB1 = nss_nisplus.so$(VERS)
diff --git a/usr/src/lib/nsswitch/nisplus/common/bootparams_getbyname.c b/usr/src/lib/nsswitch/nisplus/common/bootparams_getbyname.c
index f43ffc0fc4..5cb2b8c591 100644
--- a/usr/src/lib/nsswitch/nisplus/common/bootparams_getbyname.c
+++ b/usr/src/lib/nsswitch/nisplus/common/bootparams_getbyname.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,17 +19,21 @@
* CDDL HEADER END
*/
/*
- * nisplus/bootparams_getbyname.c -- "nisplus" backend for nsswitch
- * "bootparams" database.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * nisplus/bootparams_getbyname.c
*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
+ * nisplus backend for nsswitch bootparams database.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <nss_dbdefs.h>
#include <strings.h>
+#include <stdlib.h>
#include "nisplus_common.h"
#include "nisplus_tables.h"
@@ -39,7 +42,7 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nisplus_lookup(be, argp, BOOTPARAM_TAG_KEY,
argp->key.name));
@@ -47,22 +50,20 @@ getbyname(be, a)
/*
* place the results from the nis_object structure into argp->buf.buffer
- * (hid argp->buf.buflen) that was supplied by the caller.
+ * that was supplied by the caller.
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *val;
- int buflen = argp->buf.buflen;
- struct entry_col *ecol;
- int len;
-
- buffer = argp->buf.buffer;
+ char *buffer, *val;
+ int buflen, vallen;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore it.
@@ -79,18 +80,28 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * datum
- */
- EC_SET(ecol, BOOTPARAM_NDX_DATUM, len, val);
- if (len < 2) {
- *buffer = 0;
- return (NSS_STR_PARSE_SUCCESS);
- }
- if (len > buflen)
- return (NSS_STR_PARSE_ERANGE);
- strncpy(buffer, val, len);
+ /* datum */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, BOOTPARAM_NDX_DATUM, vallen, val);
+ buflen = vallen + 1;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* include trailing null in length */
+ be->buflen = buflen;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+ }
+ (void) snprintf(buffer, buflen, "%s", val);
+#ifdef DEBUG
+ (void) fprintf(stdout, "bootparams [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -106,5 +117,5 @@ _nss_nisplus_bootparams_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(bootparams_ops,
sizeof (bootparams_ops) / sizeof (bootparams_ops[0]),
- BOOTPARAM_TBLNAME, nis_object2ent));
+ BOOTPARAM_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/ether_addr.c b/usr/src/lib/nsswitch/nisplus/common/ether_addr.c
index 3d0fbb25e1..346188c4b4 100644
--- a/usr/src/lib/nsswitch/nisplus/common/ether_addr.c
+++ b/usr/src/lib/nsswitch/nisplus/common/ether_addr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,16 @@
* CDDL HEADER END
*/
/*
- * nisplus/ether_addr.c -- "nisplus" backend for nsswitch "ethers" database
- *
- * Copyright 1988-1992,2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * nisplus/ether_addr.c
+ *
+ * nisplus backend for nsswitch "ethers" database
+ */
+
#pragma ident "%Z%%M% %I% %E% SMI"
/*
@@ -36,6 +39,7 @@
* bytes are always in network order.
*/
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -67,43 +71,30 @@ getbyether(be, a)
char etherstr[18];
uchar_t *e = argp->key.ether;
- (void) sprintf(etherstr, "%x:%x:%x:%x:%x:%x",
+ (void) snprintf(etherstr, 18, "%x:%x:%x:%x:%x:%x",
*e, *(e + 1), *(e + 2), *(e + 3), *(e + 4), *(e + 5));
return (_nss_nisplus_lookup(be, argp, ETHER_TAG_ADDR,
etherstr));
}
/*
- * Place the resulting struct ether_addr from the nis_object structure into
- * argp->buf.result only if argp->buf.result is initialized (not NULL).
- * I.e. it happens for the call ether_hostton.
- *
- * Place the resulting hostname into argp->buf.buffer only if
- * argp->buf.buffer is initialized. I.e. it happens for the call
- * ether_ntohost.
+ * Convert the ethers nisplus object into files format
*
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- uchar_t *ether = (uchar_t *)argp->buf.result;
- char *host = argp->buf.buffer;
- char *val;
- struct entry_col *ecol;
- int len;
+ char *addr, *name;
+ int addrlen, namelen;
+ struct entry_col *ecol;
/*
- * argp->buf.buflen does not make sense for ethers. It
- * is always set to 0 by the frontend. The caller only
- * passes a hostname pointer in case of ether_ntohost,
- * that is assumed to be big enough. For ether_hostton,
- * the struct ether_addr passed is a fixed size.
- *
* If we got more than one nis_object, we just ignore it.
* Although it should never have happened.
*
@@ -118,46 +109,29 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * get ether addr
- *
- * ether_hostton
- */
- if (ether) {
- int i;
- unsigned int t[6];
-
- EC_SET(ecol, ETHER_NDX_ADDR, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- i = sscanf(val, "%x:%x:%x:%x:%x:%x",
- &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]);
- if (i != ETHERADDRL)
- return (NSS_STR_PARSE_PARSE);
- for (i = 0; i < ETHERADDRL; i++)
- *(ether + i) = (uchar_t)t[i];
+ /* addr */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, ETHER_NDX_ADDR, addrlen, addr);
+
+ /* name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, ETHER_NDX_NAME, namelen, name);
+
+ /* skip comment */
/*
- * get hostname
+ * can't use argp->buf.result == NULL test to determine if
+ * the caller is nscd or not.
*
- * ether_ntohost
+ * exclude trailing null from length
*/
- } else if (host) {
- EC_SET(ecol, ETHER_NDX_NAME, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- /*
- * The interface does not let the caller specify how long is
- * the buffer pointed by host. We make a safe assumption that
- * the callers will always give MAXHOSTNAMELEN. In any case,
- * it is the only finite number we can lay our hands on in
- * case of runaway strings, memory corruption etc.
- */
- if (len > MAXHOSTNAMELEN)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(host, val);
- }
+ be->buflen = addrlen + namelen + 1;
+ if ((be->buffer = calloc(1, be->buflen + 1)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ (void) snprintf(be->buffer, be->buflen + 1, "%s %s", addr, name);
+#ifdef DEBUG
+ (void) fprintf(stdout, "ethers [%s]\n", be->buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -174,5 +148,5 @@ _nss_nisplus_ethers_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(ethers_ops,
sizeof (ethers_ops) / sizeof (ethers_ops[0]),
- ETHER_TBLNAME, nis_object2ent));
+ ETHER_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getauthattr.c b/usr/src/lib/nsswitch/nisplus/common/getauthattr.c
index 5c9d63545a..cb3d76efd7 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getauthattr.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getauthattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -44,23 +43,20 @@ getbynam(nisplus_backend_ptr_t be, void *a)
}
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2authstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
+nis_object2authstr(int nobj, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp)
{
- int len;
- int buflen = argp->buf.buflen;
- char *buffer, *limit, *val, *endnum, *nullstring;
- char *empty = "";
- authstr_t *auth;
+ char *buffer, *name, *res1, *res2;
+ char *shortdesc, *longdesc, *attr;
+ int buflen, namelen, res1len, res2len;
+ int shortdesclen, longdesclen, attrlen;
struct entry_col *ecol;
- limit = argp->buf.buffer + buflen;
- auth = (authstr_t *)argp->buf.result;
- buffer = argp->buf.buffer;
-
/*
* If we got more than one nis_object, we just ignore object(s)
* except the first. Although it should never have happened.
@@ -76,96 +72,48 @@ nis_object2authstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * authstr->name: authorization name
- */
- EC_SET(ecol, AUTHATTR_NDX_NAME, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- auth->name = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->name, val);
- nullstring = (buffer - 1);
-
- /*
- * authstr->res1: reserved field 1
- */
- EC_SET(ecol, AUTHATTR_NDX_RES1, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- auth->res1 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->res1, val);
- nullstring = (buffer - 1);
-
- /*
- * authstr->res2: reserved field 2
- */
- EC_SET(ecol, AUTHATTR_NDX_RES2, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- auth->res2 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->res2, val);
- nullstring = (buffer - 1);
-
- /*
- * authstr->short_desc: short description
- */
- EC_SET(ecol, AUTHATTR_NDX_SHORTDESC, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- auth->short_desc = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->short_desc, val);
- nullstring = (buffer - 1);
-
- /*
- * authstr->long_desc: long description
- */
- EC_SET(ecol, AUTHATTR_NDX_LONGDESC, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
+ /* authorization name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, AUTHATTR_NDX_NAME, namelen, name);
+
+ /* reserved field 1 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUTHATTR_NDX_RES1, res1len, res1);
+
+ /* reserved field 2 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUTHATTR_NDX_RES2, res2len, res2);
+
+ /* short description */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUTHATTR_NDX_SHORTDESC,
+ shortdesclen, shortdesc);
+
+ /* long description */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUTHATTR_NDX_LONGDESC,
+ longdesclen, longdesc);
+
+ /* key-value pairs of attributes */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUTHATTR_NDX_ATTR,
+ attrlen, attr);
+
+ buflen = namelen + res1len + res2len + shortdesclen
+ + longdesclen + attrlen + 6;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
- auth->long_desc = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->long_desc, val);
- nullstring = (buffer - 1);
-
- /*
- * authstr->attrs: key-value pairs of attributes
- */
- EC_SET(ecol, AUTHATTR_NDX_ATTR, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- auth->attr = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(auth->attr, val);
- nullstring = (buffer - 1);
-
+ (void) snprintf(buffer, buflen, "%s:%s:%s:%s:%s:%s",
+ name, res1, res2, shortdesc, longdesc, attr);
+#ifdef DEBUG
+ (void) fprintf(stdout, "authattr [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -177,6 +125,7 @@ static nisplus_backend_op_t authattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_auth_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nisplus/common/getauuser.c b/usr/src/lib/nsswitch/nisplus/common/getauuser.c
index b7ab478db4..23429494cf 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getauuser.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getauuser.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -42,7 +41,6 @@
#include <secdb.h>
#include "nisplus_tables.h"
-
static nss_status_t
getbynam(nisplus_backend_ptr_t be, void *a)
{
@@ -53,22 +51,18 @@ getbynam(nisplus_backend_ptr_t be, void *a)
}
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2auuser(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
+nis_object2auuser(int nobj, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp)
{
- int len;
- int buflen = argp->buf.buflen;
- char *p, *buffer, *limit, *val, *endnum, *nullstring;
- char *empty = "";
- au_user_str_t *au_user;
+ char *buffer, *name, *always, *never;
+ int buflen, namelen, alwayslen, neverlen;
struct entry_col *ecol;
- limit = argp->buf.buffer + buflen;
- au_user = (au_user_str_t *)argp->buf.result;
- buffer = argp->buf.buffer;
/*
* If we got more than one nis_object, we just ignore object(s) except
* the first. Although it should never have happened.
@@ -82,51 +76,38 @@ nis_object2auuser(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * au_user->name: user name
- */
- EC_SET(ecol, AUDITUSER_NDX_NAME, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- au_user->au_name = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(au_user->au_name, val);
- nullstring = (buffer - 1);
+ /* user name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, AUDITUSER_NDX_NAME,
+ namelen, name);
- /*
- * au_user->au_always: always audited events
- */
- EC_SET(ecol, AUDITUSER_NDX_ALWAYS, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- au_user->au_always = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(au_user->au_always, val);
- nullstring = (buffer - 1);
+ /* always audited events */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUDITUSER_NDX_ALWAYS,
+ alwayslen, always);
- /*
- * au_user->au_never: never audited events
- */
- EC_SET(ecol, AUDITUSER_NDX_NEVER, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- au_user->au_never = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(au_user->au_never, val);
- nullstring = (buffer - 1);
+ /* never audited events */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, AUDITUSER_NDX_NEVER,
+ neverlen, never);
+ buflen = namelen + alwayslen + neverlen + 3;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+ }
+ (void) snprintf(buffer, buflen, "%s:%s:%s",
+ name, always, never);
+#ifdef DEBUG
+ (void) fprintf(stdout, "audituser [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -138,6 +119,7 @@ static nisplus_backend_op_t auuser_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_audit_user_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nisplus/common/getexecattr.c b/usr/src/lib/nsswitch/nisplus/common/getexecattr.c
index a0f3fb65cc..8a60c77e75 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getexecattr.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getexecattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -88,8 +87,7 @@ _print_execstr(execstr_t *exec)
static nss_status_t
_exec_process_val(_exec_nisplus_args * eargp, nis_object * obj)
{
- int parse_stat;
- nss_status_t res;
+ int parsestat;
nss_XbyY_args_t *argp = eargp->argp;
nisplus_backend_t *be = eargp->be;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
@@ -98,30 +96,70 @@ _exec_process_val(_exec_nisplus_args * eargp, nis_object * obj)
(void) fprintf(stdout, "\n[getexecattr.c: _exec_process_val]\n");
#endif /* DEBUG */
- parse_stat = (be->obj2ent) (1, obj, argp); /* passing one obj */
- switch (parse_stat) {
- case NSS_STR_PARSE_SUCCESS:
+ /* passing one obj */
+ parsestat = (be->obj2str) (1, obj, be, argp);
+ if (parsestat != NSS_STR_PARSE_SUCCESS)
+ goto fail;
+
+ /*
+ * If caller is nscd's switch engine, the data
+ * will be in argp->buf.buffer. nscd does not
+ * support GET_ALL at this time so return
+ * success from here.
+ */
+ if (argp->buf.result == NULL && be->buffer == NULL) {
+ argp->returnval = argp->buf.buffer;
+ if (argp->buf.buffer != NULL)
+ argp->returnlen = strlen(argp->buf.buffer);
+ return (NSS_SUCCESS);
+ }
+
+ /*
+ * If the data is in be->buffer it needs
+ * to be marshalled.
+ */
+ if (argp->str2ent == NULL) {
+ parsestat = NSS_STR_PARSE_PARSE;
+ goto fail;
+ }
+ parsestat = (*argp->str2ent)(be->buffer,
+ be->buflen,
+ argp->buf.result,
+ argp->buf.buffer,
+ argp->buf.buflen);
+ if (parsestat == NSS_STR_PARSE_SUCCESS) {
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
argp->returnval = argp->buf.result;
- res = NSS_SUCCESS;
- if (_priv_exec->search_flag == GET_ALL) {
- if (_doexeclist(argp) == 0) {
- res = NSS_UNAVAIL;
- }
+ if (argp->buf.result != NULL)
+ argp->returnlen = 1;
+ else if (argp->buf.buffer != NULL) {
+ argp->returnval = argp->buf.buffer;
+ argp->returnlen = strlen(argp->buf.buffer);
}
- break;
- case NSS_STR_PARSE_ERANGE:
- argp->erange = 1;
- res = NSS_NOTFOUND; /* We won't find this otherwise, anyway */
- break;
- case NSS_STR_PARSE_PARSE:
- res = NSS_NOTFOUND;
- break;
- default:
- res = NSS_UNAVAIL;
- break;
+ if (_priv_exec->search_flag == GET_ALL)
+ if (_doexeclist(argp) == 0)
+ return (NSS_UNAVAIL);
+ return (NSS_SUCCESS);
}
- return (res);
+fail:
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
+ if (parsestat == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ /* We won't find this otherwise, anyway */
+ return (NSS_NOTFOUND);
+ } else if (parsestat == NSS_STR_PARSE_PARSE) {
+ return (NSS_NOTFOUND);
+ }
+ return (NSS_UNAVAIL);
}
@@ -131,17 +169,16 @@ _exec_process_val(_exec_nisplus_args * eargp, nis_object * obj)
* returns 0 if - no matching entry found,
* matching entry found and next match needed.
*/
+/*ARGSUSED*/
static int
check_match(nis_name table, nis_object * obj, void *eargs)
{
- int len;
- int status = 0;
- char *p, *val;
+ int len, status = 0;
+ char *val;
struct entry_col *ecol;
nss_status_t res;
_exec_nisplus_args *eargp = (_exec_nisplus_args *)eargs;
nss_XbyY_args_t *argp = eargp->argp;
- nisplus_backend_t *be = eargp->be;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
const char *type = _priv_exec->type;
const char *policy = _priv_exec->policy;
@@ -171,7 +208,7 @@ check_match(nis_name table, nis_object * obj, void *eargs)
* check policy; it was not a searchable column in old servers.
*/
EC_SET(ecol, EXECATTR_NDX_POLICY, len, val);
- if ((len == NULL) || (strcmp(val, policy) != 0)) {
+ if ((len == 0) || (strcmp(val, policy) != 0)) {
return (0);
}
}
@@ -181,7 +218,7 @@ check_match(nis_name table, nis_object * obj, void *eargs)
* check type
*/
EC_SET(ecol, EXECATTR_NDX_TYPE, len, val);
- if ((len == NULL) || (strcmp(val, type) != 0)) {
+ if ((len == 0) || (strcmp(val, type) != 0)) {
return (0);
}
}
@@ -210,11 +247,9 @@ _exec_nisplus_lookup(nisplus_backend_t *be,
nss_XbyY_args_t *argp,
int getby_flag)
{
- int status;
char key[MAX_INPUT];
char policy_key[POLICY_LEN];
const char *column1, *key1, *column2, *key2;
- nis_object *obj;
nis_result *r = NULL;
nss_status_t res = NSS_NOTFOUND;
_exec_nisplus_args eargs;
@@ -347,7 +382,6 @@ getbyid(nisplus_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
#ifdef DEBUG
(void) fprintf(stdout, "\n[getexecattr.c: getbyid]\n");
@@ -369,7 +403,6 @@ getbynameid(nisplus_backend_ptr_t be, void *a)
{
nss_status_t res;
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
- _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
#ifdef DEBUG
(void) fprintf(stdout, "\n[getexecattr.c: getbynameid]\n");
@@ -387,28 +420,20 @@ getbynameid(nisplus_backend_ptr_t be, void *a)
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2execstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
+nis_object2execstr(int nobj, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp)
{
- int len;
- int buflen = argp->buf.buflen;
- char *limit, *val, *endnum, *nullstring;
- char *buffer = NULL;
- char *empty = "";
- execstr_t *exec = NULL;
+ char *buffer, *name, *type, *policy;
+ char *res1, *res2, *id, *attr;
+ int buflen, namelen, typelen, policylen;
+ int res1len, res2len, idlen, attrlen;
struct entry_col *ecol;
- limit = argp->buf.buffer + buflen;
- exec = (execstr_t *)argp->buf.result;
- buffer = argp->buf.buffer;
-
- if ((buffer == NULL) || (exec == NULL)) {
- return (NSS_STR_PARSE_PARSE);
- }
-
/*
* If we got more than one nis_object, we just ignore object(s) except
* the first. Although it should never have happened.
@@ -422,113 +447,49 @@ nis_object2execstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * execstr->name: profile name
- */
- EC_SET(ecol, EXECATTR_NDX_NAME, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->name = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->name, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->type: exec type
- */
- EC_SET(ecol, EXECATTR_NDX_TYPE, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->type = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->type, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->policy
- */
- EC_SET(ecol, EXECATTR_NDX_POLICY, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->policy = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->policy, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->res1: reserved field 1
- */
- EC_SET(ecol, EXECATTR_NDX_RES1, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->res1 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->res1, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->res2: reserved field 2
- */
- EC_SET(ecol, EXECATTR_NDX_RES2, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->res2 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->res2, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->id: unique id
- */
- EC_SET(ecol, EXECATTR_NDX_ID, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->id = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(exec->id, val);
- nullstring = (buffer - 1);
-
- /*
- * execstr->attrs: key-value pairs of attributes
- */
- EC_SET(ecol, EXECATTR_NDX_ATTR, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- exec->attr = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
+ /* profile name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, EXECATTR_NDX_NAME, namelen, name);
+
+ /* exec type */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_TYPE, typelen, type);
+
+ /* policy */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_POLICY,
+ policylen, policy);
+
+ /* reserved field 1 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_RES1, res1len, res1);
+
+ /* reserved field 2 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_RES2, res2len, res2);
+
+ /* unique id */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_ID, idlen, id);
+
+ /* key-value pairs of attributes */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, EXECATTR_NDX_ATTR, attrlen, attr);
+
+ buflen = namelen + policylen + typelen + res1len + res2len
+ + idlen + attrlen + 7;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
- strcpy(exec->attr, val);
- nullstring = (buffer - 1);
-
- exec->next = (execstr_t *)NULL;
-
+ (void) snprintf(buffer, buflen, "%s:%s:%s:%s:%s:%s:%s",
+ name, policy, type, res1, res2, id, attr);
+#ifdef DEBUG
+ (void) fprintf(stdout, "execattr [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -542,6 +503,7 @@ static nisplus_backend_op_t execattr_ops[] = {
getbynameid
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_exec_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nisplus/common/getgrent.c b/usr/src/lib/nsswitch/nisplus/common/getgrent.c
index 1b51eb5d23..5d1a5234ff 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getgrent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -72,7 +71,7 @@ getbygid(be, a)
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char gidstr[12]; /* More than enough */
- sprintf(gidstr, "%d", argp->key.gid);
+ (void) snprintf(gidstr, 12, "%ld", argp->key.gid);
return (_nss_nisplus_lookup(be, argp, GR_TAG_GID, gidstr));
}
@@ -144,7 +143,8 @@ getbymember(be, a)
* dumping all of the group entries and searching from the member
* name on our own.
*/
- sprintf(buf, "[members=%s],%s", argp->username, be->table_name);
+ (void) snprintf(buf, NIS_MAXNAMELEN, "[members=%s],%s",
+ argp->username, be->table_name);
r = __nis_list_localcb(buf, NIS_LIST_COMMON | ALL_RESULTS |
__nis_force_hard_lookups, gr_cback, &grdata);
if (r && r->status != NIS_BADATTRIBUTE) {
@@ -165,7 +165,7 @@ getbymember(be, a)
/*
- * place the results from the nis_object structure into argp->buf.result
+ * convert the nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*
* This routine does not tolerate non-numeric gr_gid. It
@@ -173,21 +173,16 @@ getbymember(be, a)
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val, *endnum, *grstart;
- int buflen = argp->buf.buflen;
- struct group *gr;
- struct entry_col *ecol;
- int len;
- char **memlist;
-
- limit = argp->buf.buffer + buflen;
- gr = (struct group *)argp->buf.result;
- buffer = argp->buf.buffer;
+ char *buffer, *name, *passwd, *gid, *members;
+ int buflen, namelen, passwdlen, gidlen, memberslen;
+ char *endnum;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore it.
@@ -204,92 +199,44 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * gr_name: group name
- */
- EC_SET(ecol, GR_NDX_NAME, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- gr->gr_name = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(gr->gr_name, val);
+ /* name: group name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, GR_NDX_NAME, namelen, name);
/*
- * gr_passwd: group passwd
- *
- * POLICY: The empty password ("") is gladly accepted.
+ * passwd: group passwd
+ * empty password ("") is gladly accepted.
*/
- EC_SET(ecol, GR_NDX_PASSWD, len, val);
- if (len == 0) {
- len = 1;
- val = "";
- }
- gr->gr_passwd = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(gr->gr_passwd, val);
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, GR_NDX_PASSWD, passwdlen, passwd);
- /*
- * gr_gid: group id
- */
- EC_SET(ecol, GR_NDX_GID, len, val);
- if (len == 0) {
+ /* gid: group id */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, GR_NDX_GID, gidlen, gid);
+ (void) strtol(gid, &endnum, 10);
+ if (*endnum != 0 || gid == endnum)
return (NSS_STR_PARSE_PARSE);
- } else {
- gr->gr_gid = strtol(val, &endnum, 10);
- if (*endnum != 0) {
- return (NSS_STR_PARSE_PARSE);
- }
- }
- /*
- * gr_mem: gid list
- *
- * We first copy the field that looks like "grp1,grp2,..,grpn\0"
- * into the buffer and advance the buffer in order to allocate
- * for the gr_mem vector. We work on the group members in place
- * in the buffer by replacing the "commas" with \0 and simulataneously
- * advance the vector and point to a member.
- *
- * POLICY: We happily accept a null gid list. NIS+ tables store
- * that as a single null character.
- */
- EC_SET(ecol, GR_NDX_MEM, len, val);
- if (len == 0) {
- len = 1;
- val = "";
- }
- grstart = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(grstart, val);
-
- gr->gr_mem = memlist = (char **)ROUND_UP(buffer, sizeof (char **));
- limit = (char *)ROUND_DOWN(limit, sizeof (char **));
-
- while ((char *)memlist < limit) {
- char c;
- char *p = grstart;
-
- if (*p != '\0') /* avoid empty string */
- *memlist++ = p;
- while ((c = *p) != '\0' && c != ',') {
- p++;
- }
- if (*p == '\0') { /* all done */
- *memlist = 0;
- break;
- }
- *p++ = '\0';
- grstart = p;
- }
- if ((char *)memlist >= limit)
- return (NSS_STR_PARSE_ERANGE);
+ /* members: gid list */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, GR_NDX_MEM, memberslen, members);
+ buflen = namelen + passwdlen + gidlen + memberslen + 4;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude the trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+ }
+ (void) snprintf(buffer, buflen, "%s:%s:%s:%s",
+ name, passwd, gid, members);
+#ifdef DEBUG
+ (void) fprintf(stdout, "group [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -310,7 +257,7 @@ _nss_nisplus_group_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(gr_ops,
sizeof (gr_ops) / sizeof (gr_ops[0]),
- GR_TBLNAME, nis_object2ent));
+ GR_TBLNAME, nis_object2str));
}
#define NEXT 0
@@ -404,7 +351,7 @@ netid_lookup(struct memdata *grdata, nisplus_backend_ptr_t be)
return (NSS_NOTFOUND);
}
- snprintf(buf, NIS_MAXNAMELEN,
+ (void) snprintf(buf, NIS_MAXNAMELEN,
"[auth_name=%d,auth_type=LOCAL],cred.%s", pw.pw_uid,
nis_domain_of(be->table_name));
@@ -436,6 +383,7 @@ netid_lookup(struct memdata *grdata, nisplus_backend_ptr_t be)
}
}
+/*ARGSUSED*/
static int
netid_cback(nis_name objname, nis_object *obj, struct memdata *g)
{
diff --git a/usr/src/lib/nsswitch/nisplus/common/gethostent.c b/usr/src/lib/nsswitch/nisplus/common/gethostent.c
index 4070316799..ed413ffe0b 100644
--- a/usr/src/lib/nsswitch/nisplus/common/gethostent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/gethostent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,11 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/gethostent.c -- NIS+ backend for nsswitch "hosts" database
*/
@@ -30,6 +31,8 @@
#include <string.h>
#include <netdb.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "nisplus_common.h"
@@ -40,7 +43,7 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
nss_status_t res;
/*
@@ -59,13 +62,13 @@ getbyaddr(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
struct in_addr addr;
char addrbuf[18];
nss_status_t res;
- memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
- inet_ntoa_r(addr, addrbuf);
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) inet_ntoa_r(addr, addrbuf);
res = _nss_nisplus_expand_lookup(be, argp, HOST_TAG_ADDR, addrbuf,
HOST_TBLNAME);
if (res != NSS_SUCCESS)
@@ -75,75 +78,121 @@ getbyaddr(be, a)
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit;
- int buflen = argp->buf.buflen;
- struct hostent *host;
- struct in_addr *addrp;
- int count, ret;
-
- limit = argp->buf.buffer + buflen;
- host = (struct hostent *)argp->buf.result;
- buffer = argp->buf.buffer;
+ return (nis_hosts_object2str(nobj, obj, be, argp, AF_INET));
+}
+
/*
- * <--------------- buffer + buflen -------------------------------------->
- * |-----------------|-----------------|----------------|----------------|
- * | pointers vector | pointers vector | aliases grow | addresses grow |
- * | for addresses | for aliases | | |
- * | this way -> | this way -> | <- this way |<- this way |
- * |-----------------|-----------------|----------------|----------------|
- * | grows in PASS 1 | grows in PASS2 | grows in PASS2 | grows in PASS 1|
- *
- *
- * ASSUME: the name and aliases columns in NIS+ tables ARE
- * null terminated.
- *
- *
- * PASS 1: get addresses
+ * Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
-
- addrp = (struct in_addr *) ROUND_DOWN(limit, sizeof (*addrp));
- host->h_addr_list = (char **) ROUND_UP(buffer, sizeof (char **));
- if ((char *)host->h_addr_list >= limit ||
- (char *)addrp <= (char *)host->h_addr_list) {
- return (NSS_STR_PARSE_ERANGE);
+int
+nis_hosts_object2str(nobj, obj, be, argp, af)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
+ int af;
+{
+ char *buffer;
+ char *cname, *name, *addr;
+ int buflen, cnamelen, namelen, addrlen;
+ int first;
+ struct in_addr addr4;
+ struct entry_col *ecol;
+
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+
+ for (first = 1; nobj > 0; nobj--, obj++) {
+ if (obj == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
+ obj->EN_data.en_cols.en_cols_len < HOST_COL) {
+ /* namespace/table/object is curdled */
+ return (NSS_STR_PARSE_PARSE);
+ }
+ ecol = obj->EN_data.en_cols.en_cols_val;
+
+ /* cname */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, HOST_NDX_CNAME,
+ cnamelen, cname);
+
+ /* addr */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, HOST_NDX_ADDR,
+ addrlen, addr);
+ if (af == AF_INET) {
+ addr4.s_addr = inet_addr(addr);
+ if (addr4.s_addr == INADDR_NONE)
+ return (NSS_STR_PARSE_PARSE);
+ }
+
+ /* name */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, HOST_NDX_NAME,
+ namelen, name);
+
+ /*
+ * newline is used to separate multiple
+ * entries. There is no newline before
+ * the first entry and after the last
+ * entry
+ */
+ if (first) {
+ first = 0;
+ } else if (buflen > 1) {
+ *buffer = '\n';
+ buffer++;
+ buflen--;
+ } else {
+ return (NSS_STR_PARSE_ERANGE);
+ }
+
+ if (namelen > 1) {
+ if ((addrlen + cnamelen + namelen + 3)
+ > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) snprintf(buffer, buflen, "%s %s %s",
+ addr, cname, name);
+ buffer += addrlen + cnamelen + namelen + 2;
+ buflen -= (addrlen + cnamelen + namelen + 2);
+ } else {
+ if ((addrlen + cnamelen + 2) > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) snprintf(buffer, buflen, "%s %s",
+ addr, cname);
+ buffer += addrlen + cnamelen + 1;
+ buflen -= (addrlen + cnamelen + 1);
+ }
}
- ret = __netdb_aliases_from_nisobj(obj, nobj, NULL,
- host->h_addr_list, (char **)&addrp, 0, &count, AF_INET);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
-
- /*
- * PASS 2: get cname and aliases
- */
-
- host->h_aliases = host->h_addr_list + count + 1;
- host->h_name = NULL;
-
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = __netdb_aliases_from_nisobj(obj, nobj, NULL, host->h_aliases,
- (char **)&addrp, &(host->h_name), &count, AF_INET);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
-
- host->h_addrtype = AF_INET;
- host->h_length = sizeof (u_int);
-
+ if (argp->buf.result != NULL) {
+ /*
+ * Some front end marshallers may require the
+ * files formatted data in a distinct buffer
+ */
+ if ((be->buffer = strdup(argp->buf.buffer)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = strlen(be->buffer);
+ }
+#ifdef DEBUG
+ (void) fprintf(stdout, "%s [%s]\n",
+ (af == AF_INET)?"hosts":"ipnodes",
+ argp->buf.buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
+
static nisplus_backend_op_t host_ops[] = {
_nss_nisplus_destr,
_nss_nisplus_endent,
@@ -160,5 +209,5 @@ _nss_nisplus_hosts_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(host_ops,
sizeof (host_ops) / sizeof (host_ops[0]),
- HOST_TBLNAME, nis_object2ent));
+ HOST_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/gethostent6.c b/usr/src/lib/nsswitch/nisplus/common/gethostent6.c
index e9633d58a0..55ca8bc5a5 100644
--- a/usr/src/lib/nsswitch/nisplus/common/gethostent6.c
+++ b/usr/src/lib/nsswitch/nisplus/common/gethostent6.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,11 @@
* CDDL HEADER END
*/
/*
- * Copyright 1988-1992, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- *
+ */
+
+/*
* nisplus/gethostent6.c -- NIS+ backend for nsswitch "ipnodes" database
*/
@@ -34,10 +35,9 @@
#include <sys/socket.h>
#include "nisplus_common.h"
#include "nisplus_tables.h"
+#include <arpa/inet.h>
#include <inet/ip6.h>
-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-
static nss_status_t
getbyname(be, a)
nisplus_backend_ptr_t be;
@@ -72,7 +72,7 @@ getbyaddr(be, a)
return (NSS_NOTFOUND);
}
- memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
if (IN6_IS_ADDR_V4MAPPED(&addr)) {
if (inet_ntop(AF_INET, (void *) &addr.s6_addr[12],
(void *)addrbuf, INET_ADDRSTRLEN) == NULL) {
@@ -93,76 +93,19 @@ getbyaddr(be, a)
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit;
- int buflen = argp->buf.buflen;
- struct hostent *host;
- struct in6_addr *addrp;
- int count, ret;
-
- limit = argp->buf.buffer + buflen;
- host = (struct hostent *)argp->buf.result;
- buffer = argp->buf.buffer;
-
-/*
- * <--------------- buffer + buflen -------------------------------------->
- * |-----------------|-----------------|----------------|----------------|
- * | pointers vector | pointers vector | aliases grow | addresses grow |
- * | for addresses | for aliases | | |
- * | this way -> | this way -> | <- this way |<- this way |
- * |-----------------|-----------------|----------------|----------------|
- * | grows in PASS 1 | grows in PASS2 | grows in PASS2 | grows in PASS 1|
- *
- *
- * ASSUME: the name and aliases columns in NIS+ tables ARE
- * null terminated.
- *
- *
- * PASS 1: get addresses
- */
-
- addrp = (struct in6_addr *)ROUND_DOWN(limit, sizeof (*addrp));
- host->h_addr_list = (char **)ROUND_UP(buffer, sizeof (char **));
- if ((char *)host->h_addr_list >= limit ||
- (char *)addrp <= (char *)host->h_addr_list) {
- return (NSS_STR_PARSE_ERANGE);
- }
-
- ret = __netdb_aliases_from_nisobj(obj, nobj, NULL,
- host->h_addr_list, (char **)&addrp, 0, &count, AF_INET6);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
-
- /*
- * PASS 2: get cname and aliases
- */
-
- host->h_aliases = host->h_addr_list + count + 1;
- host->h_name = NULL;
-
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = __netdb_aliases_from_nisobj(obj, nobj, NULL,
- host->h_aliases, (char **)&addrp, &(host->h_name), &count,
- AF_INET6);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
-
- host->h_addrtype = AF_INET6;
- host->h_length = IPV6_ADDR_LEN;
-
- return (NSS_STR_PARSE_SUCCESS);
+ return (nis_hosts_object2str(nobj, obj, be, argp, AF_INET6));
}
+
static nisplus_backend_op_t ipnodes_ops[] = {
_nss_nisplus_destr,
_nss_nisplus_endent,
@@ -179,5 +122,5 @@ _nss_nisplus_ipnodes_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(ipnodes_ops,
sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0]),
- IPNODES_TBLNAME, nis_object2ent));
+ IPNODES_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getnetent.c b/usr/src/lib/nsswitch/nisplus/common/getnetent.c
index b6efa5f950..3a0a08cb7b 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getnetent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getnetent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,11 @@
* CDDL HEADER END
*/
/*
- * getnetent.c
- *
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/getnetent.c -- NIS+ backend for nsswitch "net" database
*/
@@ -44,7 +43,7 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
/*
* Don't have to do anything for case-insensitivity; the NIS+ table
@@ -58,10 +57,10 @@ getbyaddr(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char addrstr[16];
- if (nettoa((int) argp->key.netaddr.net, addrstr, 16) != 0)
+ if (nettoa((int)argp->key.netaddr.net, addrstr, 16) != 0)
return (NSS_UNAVAIL); /* it's really ENOMEM */
return (_nss_nisplus_lookup(be, argp, NET_TAG_ADDR, addrstr));
@@ -69,66 +68,68 @@ getbyaddr(be, a)
/*
- * place the results from the nis_object structure into argp->buf.result
+ * Convert nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val;
- int buflen = argp->buf.buflen;
- struct netent *net;
- int len, ret;
- struct entry_col *ecol;
-
- limit = argp->buf.buffer + buflen;
- net = (struct netent *)argp->buf.result;
- buffer = argp->buf.buffer;
-
- /*
- * <-----buffer + buflen -------------->
- * |-----------------|----------------|
- * | pointers vector | aliases grow |
- * | for aliases | |
- * | this way -> | <- this way |
- * |-----------------|----------------|
- *
- *
- * ASSUME: name, aliases and number columns in NIS+ tables ARE
- * null terminated.
- *
- * get cname and aliases
- */
-
- net->n_aliases = (char **) ROUND_UP(buffer, sizeof (char **));
- if ((char *)net->n_aliases >= limit) {
- return (NSS_STR_PARSE_ERANGE);
+ char *buffer, *linep, *limit;
+ char *cname, *addr;
+ int buflen, cnamelen, addrlen;
+ int stat;
+ struct entry_col *ecol;
+
+ if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
+ obj->EN_data.en_cols.en_cols_len < NET_COL) {
+ /* namespace/table/object is curdled */
+ return (NSS_STR_PARSE_PARSE);
}
+ ecol = obj->EN_data.en_cols.en_cols_val;
- net->n_name = NULL;
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = netdb_aliases_from_nisobj(obj, nobj, NULL,
- net->n_aliases, &limit, &(net->n_name), &len);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
+ /* cname */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, NET_NDX_CNAME,
+ cnamelen, cname);
- /*
- * get network number from the first object
- *
- */
- ecol = obj->EN_data.en_cols.en_cols_val;
- EC_SET(ecol, NET_NDX_ADDR, len, val);
- if (len <= 0 || ((net->n_net = inet_network(val)) == (in_addr_t)-1))
+ /* addr */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, NET_NDX_ADDR,
+ addrlen, addr);
+ if (inet_network(addr) == (in_addr_t)-1)
return (NSS_STR_PARSE_PARSE);
- net->n_addrtype = AF_INET;
-
+ if (cnamelen + addrlen + 2 > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) snprintf(buffer, buflen, "%s %s", cname, addr);
+
+ linep = buffer + cnamelen + addrlen + 1;
+ limit = buffer + buflen;
+
+ stat = nis_aliases_object2str(obj, nobj, cname, NULL, linep, limit);
+ if (stat != NSS_STR_PARSE_SUCCESS)
+ return (stat);
+
+ if (argp->buf.result != NULL) {
+ /*
+ * Some front end marshallers may require the
+ * files formatted data in a distinct buffer
+ */
+ if ((be->buffer = strdup(buffer)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = strlen(buffer);
+ buffer = be->buffer;
+ }
+#ifdef DEBUG
+ (void) fprintf(stdout, "networks [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -148,7 +149,7 @@ _nss_nisplus_networks_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(net_ops,
sizeof (net_ops) / sizeof (net_ops[0]),
- NET_TBLNAME, nis_object2ent));
+ NET_TBLNAME, nis_object2str));
}
/*
@@ -159,18 +160,18 @@ _nss_nisplus_networks_constr(dummy1, dummy2, dummy3)
static int
nettoa(anet, buf, buflen)
int anet;
- char *buf;
+ char *buf;
int buflen;
{
- char *p;
- struct in_addr in;
- int addr;
+ char *p;
+ struct in_addr in;
+ int addr;
if (buf == 0)
return (1);
in = inet_makeaddr(anet, INADDR_ANY);
addr = in.s_addr;
- (void) strncpy(buf, inet_ntoa(in), buflen);
+ (void) strlcpy(buf, inet_ntoa(in), buflen);
if ((IN_CLASSA_HOST & htonl(addr)) == 0) {
p = strchr(buf, '.');
if (p == NULL)
diff --git a/usr/src/lib/nsswitch/nisplus/common/getnetgrent.c b/usr/src/lib/nsswitch/nisplus/common/getnetgrent.c
index ba4c0ce14f..36ef196801 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getnetgrent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getnetgrent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -147,7 +146,7 @@ getnetgr_get(be, a)
args->retp[i] = 0;
} else if ((len = strlen(str) + 1) <= buflen) {
args->retp[i] = buffer;
- memcpy(buffer, str, len);
+ (void) memcpy(buffer, str, len);
buffer += len;
buflen -= len;
} else {
@@ -196,7 +195,7 @@ getnetgr_destr(be, dummy)
void *dummy;
{
if (be != 0) {
- getnetgr_end(be, 0);
+ (void) getnetgr_end(be, 0);
free(be);
}
return (NSS_SUCCESS);
@@ -273,7 +272,7 @@ static void
ngt_init(ngt)
struct netgrtab *ngt;
{
- memset((void *)ngt, 0, sizeof (*ngt));
+ (void) memset((void *)ngt, 0, sizeof (*ngt));
ngt->expand_lastp = &ngt->expand_first;
}
@@ -339,7 +338,7 @@ ngt_insert(ngt, name, namelen, breadth_first)
if (cur == 0) {
return; /* Out of memory, too bad */
}
- memcpy(cur->name, name, namelen);
+ (void) memcpy(cur->name, name, namelen);
cur->name[namelen] = 0;
/* Insert in hash table */
@@ -497,26 +496,25 @@ top_down(be, groups, ngroups, func, iter_args)
int i;
/* %%% was NETGR_NDX_NAME */
- sprintf(search_crit, "[%s=%s]%s",
+ (void) snprintf(search_crit, NIS_MAXNAMELEN, "[%s=%s]%s",
NETGR_TAG_NAME, group, be->table_name);
result = _nss_nisplus_list(search_crit, 0, &r);
if (result != NSS_SUCCESS) {
- if (result == NSS_NOTFOUND) {
#ifdef DEBUG
+ if (result == NSS_NOTFOUND) {
syslog(LOG_WARNING,
"innetgr: no such NIS+ netgroup as %s",
group);
-#endif /* DEBUG */
} else {
-#ifdef DEBUG
syslog(LOG_WARNING,
"innetgr: nis_list returned [%s]",
(r == 0) ? "A null pointer !?" :
nis_sperrno(NIS_RES_STATUS(r)));
+ }
#endif /* DEBUG */
+ if (result != NSS_NOTFOUND)
done = 1; /* Give up, return result */
- }
if (r != 0) {
nis_freeresult(r);
}
@@ -750,7 +748,7 @@ every_which_way(be, args)
enum { BAD, BAD_NSS_TRYAGAIN, NO, YES } verdict;
/* Copy NIS+ search value; ==== Should really do NIS+ quoting */
-#define catquoted(to, from) strcat(to, from)
+#define catquoted(to, from) (void) strcat(to, from)
/*
* ====>
@@ -813,7 +811,7 @@ every_which_way(be, args)
pusers = nusers ? args->arg[NSS_NETGR_USER].argv : 0;
do {
if (pusers != 0) {
- strcpy(users, ",user=");
+ (void) strcpy(users, ",user=");
if (nusers != 0) {
catquoted(users, *pusers);
pusers++;
@@ -825,7 +823,7 @@ every_which_way(be, args)
phosts = nhosts ? args->arg[NSS_NETGR_MACHINE].argv : 0;
do {
if (phosts != 0) {
- strcpy(hosts, ",host=");
+ (void) strcpy(hosts, ",host=");
if (nhosts != 0) {
catquoted(hosts, *phosts);
phosts++;
@@ -833,8 +831,8 @@ every_which_way(be, args)
}
search_crit[0] = '['; /* Was temporarily a comma */
- strcat(search_crit, "]");
- strcat(search_crit, be->table_name);
+ (void) strcat(search_crit, "]");
+ (void) strcat(search_crit, be->table_name);
switch (_nss_nisplus_list(search_crit, 0, &r)) {
case NSS_SUCCESS:
break;
@@ -913,7 +911,8 @@ every_which_way(be, args)
#ifdef SEARCH_DOWN_TOO
if (top->n_total < bottom->n_total /* and a fudge factor? */) {
group = ngt_next(top);
- sprintf(search_crit, "[%s=%s]%s",
+ (void) snprintf(search_crit, NIS_MAXNAMELEN,
+ "[%s=%s]%s",
NETGR_NDX_NAME, group, be->table_name);
switch (_nss_nisplus_list(search_crit, 0, &r)) {
case NSS_SUCCESS:
@@ -962,7 +961,8 @@ every_which_way(be, args)
#endif /* SEARCH_DOWN_TOO */
group = ngt_next(bottom);
/* %%% was NETGR_NDX_GROUP */
- sprintf(search_crit, "[%s=%s],%s",
+ (void) snprintf(search_crit, NIS_MAXNAMELEN,
+ "[%s=%s],%s",
NETGR_TAG_GROUP, group, be->table_name);
switch (_nss_nisplus_list(search_crit, 0, &r)) {
case NSS_SUCCESS:
@@ -1067,10 +1067,11 @@ netgr_in(be, a)
/*ARGSUSED*/
static int
-bogus_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+bogus_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
/*
* This should never get used in the netgroup backend;
@@ -1098,5 +1099,5 @@ _nss_nisplus_netgroup_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(netgroup_ops,
sizeof (netgroup_ops) / sizeof (netgroup_ops[0]),
- NETGR_TBLNAME, bogus_object2ent));
+ NETGR_TBLNAME, bogus_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getprinter.c b/usr/src/lib/nsswitch/nisplus/common/getprinter.c
index 86566727c2..26037c0f96 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getprinter.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getprinter.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,18 +19,19 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
- *
- * nisplus/getspent.c: implementations of getspnam(), getspent(), setspent(),
- * endspent() for NIS+. We keep the shadow information in a column
- * ("shadow") of the same table that stores vanilla passwd information.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * nisplus/getprinter.c
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#pragma weak _nss_nisplus__printers_constr = _nss_nisplus_printers_constr
+#include <stdlib.h>
#include <nss_dbdefs.h>
#include "nisplus_common.h"
#include "nisplus_tables.h"
@@ -42,29 +42,26 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nisplus_lookup(be, argp, PRINTERS_TAG_KEY,
argp->key.name));
}
/*
- * place the results from the nis_object structure into argp->buf.buffer
- * (hid argp->buf.buflen) that was supplied by the caller.
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *val;
- int buflen = argp->buf.buflen;
- struct entry_col *ecol;
- int len;
-
- buffer = argp->buf.buffer;
+ char *buffer, *key, *val;
+ int buflen, keylen, vallen;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore it.
@@ -81,30 +78,30 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * key
- */
- EC_SET(ecol, PRINTERS_NDX_KEY, len, val);
- if (len < 2) {
- *buffer = 0;
- return (NSS_STR_PARSE_SUCCESS);
- }
- if (len > buflen)
- return (NSS_STR_PARSE_ERANGE);
- strncpy(buffer, val, len);
+ /* key */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PRINTERS_NDX_KEY, keylen, key);
- /*
- * datum
- */
- EC_SET(ecol, PRINTERS_NDX_DATUM, len, val);
- if (len < 2) {
- *buffer = 0;
- return (NSS_STR_PARSE_SUCCESS);
- }
- if (len > buflen)
- return (NSS_STR_PARSE_ERANGE);
- strncat(buffer, val, buflen);
+ /* datum */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PRINTERS_NDX_DATUM, vallen, val);
+ buflen = vallen + keylen + 1;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = buflen;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+ }
+ (void) snprintf(buffer, buflen, "%s%s", key, val);
+#ifdef DEBUG
+ (void) fprintf(stdout, "printers [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -116,11 +113,12 @@ static nisplus_backend_op_t printers_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_printers_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
{
return (_nss_nisplus_constr(printers_ops,
sizeof (printers_ops) / sizeof (printers_ops[0]),
- PRINTERS_TBLNAME, nis_object2ent));
+ PRINTERS_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getprofattr.c b/usr/src/lib/nsswitch/nisplus/common/getprofattr.c
index 7e6dfcb04c..c1a7111f41 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getprofattr.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getprofattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -47,19 +46,18 @@ getbynam(nisplus_backend_ptr_t be, void *a)
* place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2profstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
+nis_object2profstr(int nobj, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp)
{
- int len;
- int buflen = argp->buf.buflen;
- char *buffer, *limit, *val, *endnum, *nullstring;
- char *empty = "";
- profstr_t *prof;
+ char *buffer, *name, *res1, *res2, *desc;
+ char *attr;
+ int buflen, namelen, res1len, res2len;
+ int desclen, attrlen;
struct entry_col *ecol;
- limit = argp->buf.buffer + buflen;
- prof = (profstr_t *)argp->buf.result;
- buffer = argp->buf.buffer;
/*
* If we got more than one nis_object, we just ignore object(s) except
* the first. Although it should never have happened.
@@ -74,81 +72,41 @@ nis_object2profstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * profstr->name: profile name
- */
- EC_SET(ecol, PROFATTR_NDX_NAME, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- prof->name = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(prof->name, val);
- nullstring = (buffer - 1);
-
- /*
- * profstr->res1: reserved field 1
- */
- EC_SET(ecol, PROFATTR_NDX_RES1, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- prof->res1 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(prof->res1, val);
- nullstring = (buffer - 1);
-
- /*
- * profstr->res2: reserved field 2
- */
- EC_SET(ecol, PROFATTR_NDX_RES2, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
+ /* name: profile name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PROFATTR_NDX_NAME, namelen, name);
+
+ /* res1: reserved field 1 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PROFATTR_NDX_RES1, res1len, res1);
+
+ /* res2: reserved field 2 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PROFATTR_NDX_RES2, res2len, res2);
+
+ /* desc: description */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PROFATTR_NDX_DESC, desclen, desc);
+
+ /* attrs: key-value pairs of attributes */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PROFATTR_NDX_ATTR, attrlen, attr);
+
+ buflen = namelen + res1len + res2len + desclen + attrlen + 5;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
- prof->res2 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(prof->res2, val);
- nullstring = (buffer - 1);
-
- /*
- * profstr->desc: description
- */
- EC_SET(ecol, PROFATTR_NDX_DESC, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- prof->desc = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(prof->desc, val);
- nullstring = (buffer - 1);
-
- /*
- * profstr->attrs: key-value pairs of attributes
- */
- EC_SET(ecol, PROFATTR_NDX_ATTR, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- prof->attr = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(prof->attr, val);
- nullstring = (buffer - 1);
-
+ (void) snprintf(buffer, buflen, "%s:%s:%s:%s:%s",
+ name, res1, res2, desc, attr);
+#ifdef DEBUG
+ (void) fprintf(stdout, "profattr [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -160,6 +118,7 @@ static nisplus_backend_op_t profattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_prof_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nisplus/common/getprotoent.c b/usr/src/lib/nsswitch/nisplus/common/getprotoent.c
index aa40a34fc1..356236d2f2 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getprotoent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getprotoent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,11 @@
* CDDL HEADER END
*/
/*
- * getprotoent.c
- *
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/getprotoent.c -- NIS+ backend for nsswitch "proto" database
*/
@@ -41,7 +40,7 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
/*
* Don't have to do anything for case-insensitivity; the NIS+ table
@@ -55,74 +54,78 @@ getbynumber(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char numstr[12];
- sprintf(numstr, "%d", argp->key.number);
+ (void) snprintf(numstr, 12, "%d", argp->key.number);
return (_nss_nisplus_lookup(be, argp, PROTO_TAG_NUMBER, numstr));
}
/*
- * place the results from the nis_object structure into argp->buf.result
+ * Convert nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val;
- int buflen = argp->buf.buflen;
- struct protoent *proto;
- int len, ret;
- struct entry_col *ecol;
-
- limit = argp->buf.buffer + buflen;
- proto = (struct protoent *)argp->buf.result;
- buffer = argp->buf.buffer;
-
- /*
- * <-----buffer + buflen -------------->
- * |-----------------|----------------|
- * | pointers vector | aliases grow |
- * | for aliases | |
- * | this way -> | <- this way |
- * |-----------------|----------------|
- *
- *
- * ASSUME: name, aliases and number columns in NIS+ tables ARE
- * null terminated.
- *
- * get cname and aliases
- */
-
- proto->p_aliases = (char **) ROUND_UP(buffer, sizeof (char **));
- if ((char *)proto->p_aliases >= limit) {
- return (NSS_STR_PARSE_ERANGE);
+ char *buffer, *linep, *limit;
+ char *cname, *number, *endnum;
+ int buflen, cnamelen, numberlen;
+ int stat;
+ struct entry_col *ecol;
+
+ if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
+ obj->EN_data.en_cols.en_cols_len < PROTO_COL) {
+ /* namespace/table/object is curdled */
+ return (NSS_STR_PARSE_PARSE);
}
+ ecol = obj->EN_data.en_cols.en_cols_val;
- proto->p_name = NULL;
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = netdb_aliases_from_nisobj(obj, nobj, NULL,
- proto->p_aliases, &limit, &(proto->p_name), &len);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
+ /* cname */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PROTO_NDX_CNAME,
+ cnamelen, cname);
- /*
- * get protocol number from the first object
- *
- */
- ecol = obj->EN_data.en_cols.en_cols_val;
- EC_SET(ecol, PROTO_NDX_NUMBER, len, val);
- if (len <= 0)
+ /* number */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PROTO_NDX_NUMBER,
+ numberlen, number);
+ (void) strtol(number, &endnum, 10);
+ if (*endnum != 0 || endnum == number)
return (NSS_STR_PARSE_PARSE);
- proto->p_proto = atoi(val);
+ if (cnamelen + numberlen + 2 > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) snprintf(buffer, buflen, "%s %s", cname, number);
+
+ linep = buffer + cnamelen + numberlen + 1;
+ limit = buffer + buflen;
+
+ stat = nis_aliases_object2str(obj, nobj, cname, NULL, linep, limit);
+ if (stat != NSS_STR_PARSE_SUCCESS)
+ return (stat);
+
+ if (argp->buf.result != NULL) {
+ /*
+ * Some front end marshallers may require the
+ * files formatted data in a distinct buffer
+ */
+ if ((be->buffer = strdup(buffer)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = strlen(buffer);
+ buffer = be->buffer;
+ }
+#ifdef DEBUG
+ (void) fprintf(stdout, "protocols [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -142,5 +145,5 @@ _nss_nisplus_protocols_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(proto_ops,
sizeof (proto_ops) / sizeof (proto_ops[0]),
- PROTO_TBLNAME, nis_object2ent));
+ PROTO_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getpwnam.c b/usr/src/lib/nsswitch/nisplus/common/getpwnam.c
index 5336e05a82..19807456e5 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getpwnam.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getpwnam.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,12 @@
* CDDL HEADER END
*/
/*
- * getpwnam.c
- *
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
- * nisplus/getpwnam.c -- NIS+ backend for nsswitch "passwd" database
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * nisplus/getpwnam.c -- NIS+ backend for nsswitch "passwd" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -42,7 +41,7 @@ getbynam(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nisplus_lookup(be, argp, PW_TAG_NAME, argp->key.name));
}
@@ -52,39 +51,32 @@ getbyuid(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char uidstr[12]; /* More than enough */
- sprintf(uidstr, "%d", argp->key.uid);
+ (void) snprintf(uidstr, 12, "%ld", argp->key.uid);
return (_nss_nisplus_lookup(be, argp, PW_TAG_UID, uidstr));
}
/*
+ * convert nisplus object into files format
* place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
- *
- * This routine does not tolerate non-numeric or empty pw_uid or pw_gid.
- * Nor empty name field.
- * It will immediately flag a PARSE error and return. Returns a
- * pointer-to-a-null in case of empty gecos, home_dir, or shell fields.
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val, *endnum, *nullstring;
- int buflen = argp->buf.buflen;
- struct passwd *pw;
- struct entry_col *ecol;
- int len;
-
- limit = argp->buf.buffer + buflen;
- pw = (struct passwd *)argp->buf.result;
- buffer = argp->buf.buffer;
+ char *buffer, *name, *uid, *gid, *gecos;
+ char *dir, *shell, *endnum;
+ int buflen, namelen, uidlen, gidlen, gecoslen;
+ int dirlen, shelllen;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore object(s)
@@ -101,126 +93,53 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * pw_name: user name
- */
- EC_SET(ecol, PW_NDX_NAME, len, val);
- if (len < 2 || (*val == '\0'))
- return (NSS_STR_PARSE_PARSE);
- pw->pw_name = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(pw->pw_name, val);
- nullstring = (buffer - 1);
+ /* name: user name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PW_NDX_NAME, namelen, name);
- /*
- * pw_uid: user id
- */
- EC_SET(ecol, PW_NDX_UID, len, val);
- if (len < 2) {
- return (NSS_STR_PARSE_PARSE);
- } else {
- pw->pw_uid = strtol(val, &endnum, 10);
- if (*endnum != 0 || val == endnum) {
- return (NSS_STR_PARSE_PARSE);
- }
- }
+ /* password field is 'x' */
- /*
- * pw_passwd: user passwd. Do not HAVE to get this here
- * because the caller would do a getspnam() anyway.
- */
- EC_SET(ecol, PW_NDX_PASSWD, len, val);
- if (len < 2) {
- /*
- * don't return NULL pointer, lot of stupid programs
- * out there.
- */
- pw->pw_passwd = nullstring;
- } else {
- pw->pw_passwd = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(pw->pw_passwd, val);
- }
+ /* uid: user id. Must be numeric */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PW_NDX_UID, uidlen, uid);
+ (void) strtol(uid, &endnum, 10);
+ if (*endnum != 0 || uid == endnum)
+ return (NSS_STR_PARSE_PARSE);
- /*
- * pw_gid: user's primary group id.
- */
- EC_SET(ecol, PW_NDX_GID, len, val);
- if (len < 2) {
+ /* gid: primary group id. Must be numeric */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PW_NDX_GID, gidlen, gid);
+ (void) strtol(gid, &endnum, 10);
+ if (*endnum != 0 || gid == endnum)
return (NSS_STR_PARSE_PARSE);
- } else {
- pw->pw_gid = strtol(val, &endnum, 10);
- if (*endnum != 0 || val == endnum) {
- return (NSS_STR_PARSE_PARSE);
- }
- }
- /*
- * pw_gecos: user's real name.
- */
- EC_SET(ecol, PW_NDX_GCOS, len, val);
- if (len < 2) {
- /*
- * don't return NULL pointer, lot of stupid programs
- * out there.
- */
- pw->pw_gecos = nullstring;
- } else {
- pw->pw_gecos = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(pw->pw_gecos, val);
- }
+ /* gecos: user's real name */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PW_NDX_GCOS, gecoslen, gecos);
- /*
- * pw_dir: user's home directory
- */
- EC_SET(ecol, PW_NDX_HOME, len, val);
- if (len < 2) {
- /*
- * don't return NULL pointer, lot of stupid programs
- * out there.
- */
- pw->pw_dir = nullstring;
- } else {
- pw->pw_dir = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(pw->pw_dir, val);
- }
+ /* dir: user's home directory */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PW_NDX_HOME, dirlen, dir);
- /*
- * pw_shell: user's login shell
- */
- EC_SET(ecol, PW_NDX_SHELL, len, val);
- if (len < 2) {
- /*
- * don't return NULL pointer, lot of stupid programs
- * out there.
- */
- pw->pw_shell = nullstring;
+ /* shell: user's login shell */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PW_NDX_SHELL, shelllen, shell);
+
+ buflen = namelen + uidlen + gidlen + gecoslen +
+ dirlen + shelllen + 8;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* include trailing null in length */
+ be->buflen = buflen;
+ buffer = be->buffer;
} else {
- pw->pw_shell = buffer;
- buffer += len;
- if (buffer >= limit)
+ if (buflen > argp->buf.buflen)
return (NSS_STR_PARSE_ERANGE);
- strcpy(pw->pw_shell, val);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
-
- /*
- * pw_age and pw_comment shouldn't be used anymore, but various things
- * (allegedly in.ftpd) merrily do strlen() on them anyway, so we
- * keep the peace by returning a zero-length string instead of a
- * null pointer.
- */
- pw->pw_age = pw->pw_comment = nullstring;
-
+ (void) snprintf(buffer, buflen, "%s:x:%s:%s:%s:%s:%s",
+ name, uid, gid, gecos, dir, shell);
+#ifdef DEBUG
+ (void) fprintf(stdout, "passwd [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -240,5 +159,5 @@ _nss_nisplus_passwd_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(pw_ops,
sizeof (pw_ops) / sizeof (pw_ops[0]),
- PW_TBLNAME, nis_object2ent));
+ PW_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getrpcent.c b/usr/src/lib/nsswitch/nisplus/common/getrpcent.c
index aea3a5865d..0075a90fd9 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getrpcent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getrpcent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,11 @@
* CDDL HEADER END
*/
/*
- * getrpcent.c
- *
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/getrpcent.c -- NIS+ backend for nsswitch "rpc" database
*/
@@ -42,7 +41,7 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
/*
* Don't have to do anything for case-insensitivity; the NIS+ table
@@ -56,74 +55,78 @@ getbynumber(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char numstr[12];
- sprintf(numstr, "%d", argp->key.number);
+ (void) snprintf(numstr, 12, "%d", argp->key.number);
return (_nss_nisplus_lookup(be, argp, RPC_TAG_NUMBER, numstr));
}
/*
- * place the results from the nis_object structure into argp->buf.result
+ * Convert nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val;
- int buflen = argp->buf.buflen;
- struct rpcent *rpc;
- int len, ret;
- struct entry_col *ecol;
-
- limit = argp->buf.buffer + buflen;
- rpc = (struct rpcent *)argp->buf.result;
- buffer = argp->buf.buffer;
-
- /*
- * <-----buffer + buflen -------------->
- * |-----------------|----------------|
- * | pointers vector | aliases grow |
- * | for aliases | |
- * | this way -> | <- this way |
- * |-----------------|----------------|
- *
- *
- * ASSUME: name, aliases and number columns in NIS+ tables ARE
- * null terminated.
- *
- * get cname and aliases
- */
-
- rpc->r_aliases = (char **) ROUND_UP(buffer, (sizeof (char **)));
- if ((char *)rpc->r_aliases >= limit) {
- return (NSS_STR_PARSE_ERANGE);
+ char *buffer, *linep, *limit;
+ char *cname, *number, *endnum;
+ int buflen, cnamelen, numberlen;
+ int stat;
+ struct entry_col *ecol;
+
+ if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
+ obj->EN_data.en_cols.en_cols_len < RPC_COL) {
+ /* namespace/table/object is curdled */
+ return (NSS_STR_PARSE_PARSE);
}
+ ecol = obj->EN_data.en_cols.en_cols_val;
- rpc->r_name = NULL;
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = netdb_aliases_from_nisobj(obj, nobj, NULL,
- rpc->r_aliases, &limit, &(rpc->r_name), &len);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
+ /* cname */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, RPC_NDX_CNAME,
+ cnamelen, cname);
- /*
- * get program number from the first object
- *
- */
- ecol = obj->EN_data.en_cols.en_cols_val;
- EC_SET(ecol, RPC_NDX_NUMBER, len, val);
- if (len <= 0)
+ /* number */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, RPC_NDX_NUMBER,
+ numberlen, number);
+ (void) strtol(number, &endnum, 10);
+ if (*endnum != 0 || endnum == number)
return (NSS_STR_PARSE_PARSE);
- rpc->r_number = atoi(val);
+ if (cnamelen + numberlen + 2 > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) snprintf(buffer, buflen, "%s %s", cname, number);
+
+ linep = buffer + cnamelen + numberlen + 1;
+ limit = buffer + buflen;
+
+ stat = nis_aliases_object2str(obj, nobj, cname, NULL, linep, limit);
+ if (stat != NSS_STR_PARSE_SUCCESS)
+ return (stat);
+
+ if (argp->buf.result != NULL) {
+ /*
+ * Some front end marshallers may require the
+ * files formatted data in a distinct buffer
+ */
+ if ((be->buffer = strdup(buffer)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ be->buflen = strlen(buffer);
+ buffer = be->buffer;
+ }
+#ifdef DEBUG
+ (void) fprintf(stdout, "rpc [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -143,5 +146,5 @@ _nss_nisplus_rpc_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(rpc_ops,
sizeof (rpc_ops) / sizeof (rpc_ops[0]),
- RPC_TBLNAME, nis_object2ent));
+ RPC_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getservent.c b/usr/src/lib/nsswitch/nisplus/common/getservent.c
index fc932dfdb6..b3138f8c1a 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getservent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getservent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,11 +19,11 @@
* CDDL HEADER END
*/
/*
- * getservent.c
- *
- * Copyright (c) 1988-1992 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/getservent.c -- NIS+ backend for nsswitch "serv" database
*/
@@ -41,13 +40,13 @@ getbyname(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
/*
* Don't have to do anything for case-insensitivity; the NIS+ table
* has the right flags enabled in the 'cname' and 'name' columns.
*
- * Make sure that nis_object2ent would cull out only those entries
+ * Make sure that nis_object2str would cull out only those entries
* with the given protocol if it is non-NULL, or the first one it
* finds in the nis_object if user supplied proto is NULL.
*/
@@ -60,124 +59,109 @@ getbyport(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
char portstr[12];
/*
- * Make sure that nis_object2ent would cull out only those entries
+ * Make sure that nis_object2str would cull out only those entries
* with the given protocol if it is non-NULL, or the first one it
* finds in the nis_object if user supplied proto is NULL.
*/
- sprintf(portstr, "%d", ntohs((u_short)argp->key.serv.serv.port));
+ (void) snprintf(portstr, 12, "%d",
+ ntohs((ushort_t)argp->key.serv.serv.port));
return (_nss_nisplus_lookup(be, argp, SERV_TAG_PORT, portstr));
}
/*
- * place the results from the nis_object structure into argp->buf.result
+ * Convert nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- char *buffer, *limit, *val;
- int buflen = argp->buf.buflen;
- struct servent *serv;
- int len, ret;
- struct entry_col *ecol;
- const char *proto = argp->key.serv.proto;
- int i;
-
- limit = argp->buf.buffer + buflen;
- serv = (struct servent *)argp->buf.result;
- buffer = argp->buf.buffer;
+ char *buffer, *linep, *limit;
+ char *cname, *port, *proto, *endnum;
+ int buflen, cnamelen, portlen, protolen;
+ const char *protokey;
+ int protokeylen, stat;
+ struct entry_col *ecol;
- /*
- * If the caller does not care about a specific protocol
- * (udp or tcp usually), pick the one from the first nis_object
- * and parse all the entries associated with only this protocol.
- * NULL proto is also specified by getservent() functions. We
- * end up doing extraneous work in the case.
- */
- if (proto == NULL) {
+ protokey = argp->key.serv.proto;
+ protokeylen = (protokey) ? strlen(protokey) : 0;
+ for (; nobj > 0; obj++, nobj--) {
if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
obj->EN_data.en_cols.en_cols_len < SERV_COL) {
+ /* namespace/table/object is curdled */
return (NSS_STR_PARSE_PARSE);
}
ecol = obj->EN_data.en_cols.en_cols_val;
- EC_SET(ecol, SERV_NDX_PROTO, len, proto);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- } else {
- len = strlen(proto) + 1;
- }
- /*
- * Return (a copy of) proto in serv->s_proto
- */
- if (buffer + len > limit) {
- return (NSS_STR_PARSE_ERANGE);
+
+ /* protocol */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, SERV_NDX_PROTO,
+ protolen, proto);
+ if (protokey != NULL) {
+ if (protolen != protokeylen ||
+ strncasecmp(proto, protokey, protolen) != 0)
+ continue;
+ }
+
+ /*
+ * If the caller does not care about a specific protocol
+ * (udp or tcp usually), pick the one from the first nis_object
+ * and parse all the entries associated with only this protocol.
+ * NULL proto is also specified by getservent() functions. We
+ * end up doing extraneous work in the case.
+ */
+ break;
}
- memcpy(buffer, proto, len);
- serv->s_proto = buffer;
- buffer += len;
- buflen -= len;
- /*
- * <-----buffer + buflen -------------->
- * |-----------------|----------------|
- * | pointers vector | aliases grow |
- * | for aliases | |
- * | this way -> | <- this way |
- * |-----------------|----------------|
- *
- *
- * ASSUME: name, aliases, proto and port columns in NIS+ tables ARE
- * null terminated.
- *
- * get cname and aliases
- */
+ if (nobj <= 0)
+ return (NSS_STR_PARSE_PARSE);
+
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
+
+ /* cname */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, SERV_NDX_CNAME, cnamelen, cname);
- serv->s_aliases = (char **) ROUND_UP(buffer, sizeof (char **));
- if ((char *)serv->s_aliases >= limit) {
+ /* port */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, SERV_NDX_PORT, portlen, port);
+ (void) strtol(port, &endnum, 10);
+ if (*endnum != 0 || endnum == port)
+ return (NSS_STR_PARSE_PARSE);
+
+ if (cnamelen + portlen + protolen + 3 > buflen)
return (NSS_STR_PARSE_ERANGE);
- }
+ (void) snprintf(buffer, buflen, "%s %s/%s", cname, port, proto);
- serv->s_name = NULL;
+ linep = buffer + cnamelen + portlen + protolen + 2;
+ limit = buffer + buflen;
- /*
- * Assume that CNAME is the first column and NAME the second.
- */
- ret = netdb_aliases_from_nisobj(obj, nobj, proto,
- serv->s_aliases, &limit, &(serv->s_name), &len);
- if (ret != NSS_STR_PARSE_SUCCESS)
- return (ret);
+ stat = nis_aliases_object2str(obj, nobj, cname, proto, linep, limit);
+ if (stat != NSS_STR_PARSE_SUCCESS)
+ return (stat);
- /*
- * Read port from the first object having the desired protocol.
- * There is guaranteed to be at least one such object, or
- * netdb_aliases_from_nisobj() wouldn't have returned SUCCESS.
- */
- for (i = 0; i < nobj; i++) {
- ecol = obj[i].EN_data.en_cols.en_cols_val;
- EC_SET(ecol, SERV_NDX_PROTO, len, val);
- if (len < 2)
+ if (argp->buf.result != NULL) {
+ /*
+ * Some front end marshallers may require the
+ * files formatted data in a distinct buffer
+ */
+ if ((be->buffer = strdup(buffer)) == NULL)
return (NSS_STR_PARSE_PARSE);
- if (strcmp(proto, val) == 0)
- break;
+ be->buflen = strlen(buffer);
+ buffer = be->buffer;
}
- if (i == nobj) { /* none found... can't happen, but what the heck */
- return (NSS_STR_PARSE_PARSE);
- }
- EC_SET(ecol, SERV_NDX_PORT, len, val);
- if (len < 2) {
- return (NSS_STR_PARSE_PARSE);
- }
- serv->s_port = htons((u_short)atoi(val));
-
+#ifdef DEBUG
+ (void) fprintf(stdout, "services [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -197,5 +181,5 @@ _nss_nisplus_services_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(serv_ops,
sizeof (serv_ops) / sizeof (serv_ops[0]),
- SERV_TBLNAME, nis_object2ent));
+ SERV_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getspent.c b/usr/src/lib/nsswitch/nisplus/common/getspent.c
index 028a37ad98..dd246e3b76 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getspent.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getspent.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,9 +19,11 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1988-1995 Sun Microsystems Inc
- * All Rights Reserved.
- *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/getspent.c: implementations of getspnam(), getspent(), setspent(),
* endspent() for NIS+. We keep the shadow information in a column
* ("shadow") of the same table that stores vanilla passwd information.
@@ -62,8 +63,8 @@ getbynam(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
- struct spwd *sp = (struct spwd *) argp->buf.result;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ struct spwd *sp = (struct spwd *)argp->buf.result;
int buflen = argp->buf.buflen;
nss_status_t status;
const char *username;
@@ -76,12 +77,17 @@ getbynam(be, a)
_mutex_lock(&one_lane);
/*
- * There is a dirty little private protocol with the nis_object2ent()
+ * There is a dirty little private protocol with the nis_object2str()
* routine below: it gives us back a uid in the argp->key.uid
* field. Since "key" is a union, and we're using key.name,
* we save/restore it in case anyone cares.
+ *
+ * NSS2: be->flag is used to indicate *NP* case since we
+ * may not have the shadow passwd available at this point
+ * if called by nscd's switch.
*/
username = argp->key.name;
+ be->flag = 0;
status = _nss_nisplus_lookup(be, argp, PW_TAG_NAME, username);
@@ -95,13 +101,13 @@ getbynam(be, a)
/* fix for bugid 4301477 DELETED if (_thr_main() != -1) goto out; */
- if (!(status == NSS_SUCCESS && argp->returnval != 0 &&
- sp->sp_pwdp != 0 && strcmp(sp->sp_pwdp, "*NP*") == 0))
+ if (status != NSS_SUCCESS || argp->returnval == 0 || be->flag == 0)
goto out;
/* Get our current euid and that of the entry */
orig_uid = geteuid();
entry_uid = argp->key.uid;
+ be->flag = 0;
/*
* If the entry uid differs from our own euid, set our euid to
@@ -116,10 +122,10 @@ getbynam(be, a)
* results.
*/
if (key_secretkey_is_set_g(0, 0) &&
- ((save_buf = (char *) malloc(buflen)) != 0)) {
+ ((save_buf = (char *)malloc(buflen)) != 0)) {
/* Save the old results in case the new lookup fails */
- memcpy(save_buf, argp->buf.buffer, buflen);
+ (void) memcpy(save_buf, argp->buf.buffer, buflen);
save_sp = *sp;
/* Do the lookup (this time as the user). */
@@ -128,7 +134,8 @@ getbynam(be, a)
/* If it failed, restore the old results */
if (status != NSS_SUCCESS) {
- memcpy(argp->buf.buffer, save_buf, buflen);
+ (void) memcpy(argp->buf.buffer, save_buf,
+ buflen);
*sp = save_sp;
status = NSS_SUCCESS;
}
@@ -137,7 +144,7 @@ getbynam(be, a)
}
/* Set uid back */
- seteuid(orig_uid);
+ (void) seteuid(orig_uid);
}
out:
@@ -154,24 +161,17 @@ out:
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- struct spwd *sp = (struct spwd *) argp->buf.result;
- char *buffer = argp->buf.buffer;
- int buflen = argp->buf.buflen;
- char *limit = buffer + buflen;
-
- struct entry_col *ecol;
- char *val;
- int len;
-
- char *endnum;
- uid_t uid;
- char *p;
- long x;
+ char *buffer, *name, *passwd, *shadow;
+ int buflen, namelen, passwdlen, shadowlen;
+ char *endnum, *uidstr;
+ int uidlen;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore it.
@@ -188,47 +188,16 @@ nis_object2ent(nobj, obj, argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * sp_namp: user name
- */
- EC_SET(ecol, PW_NDX_NAME, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- sp->sp_namp = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(sp->sp_namp, val);
+ /* name: user name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PW_NDX_NAME, namelen, name);
- /*
- * sp_pwdp: password
- */
- EC_SET(ecol, PW_NDX_PASSWD, len, val);
- if (len < 2) {
- /*
- * don't return NULL pointer, lot of stupid programs
- * out there.
- */
- *buffer = '\0';
- sp->sp_pwdp = buffer++;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- } else {
- sp->sp_pwdp = buffer;
- buffer += len;
- if (buffer >= limit)
- return (NSS_STR_PARSE_ERANGE);
- strcpy(sp->sp_pwdp, val);
- }
+ /* passwd */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PW_NDX_PASSWD, passwdlen, passwd);
- /*
- * get uid
- */
- EC_SET(ecol, PW_NDX_UID, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- uid = strtol(val, &endnum, 10);
- if (*endnum != 0)
+ /* uid */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, PW_NDX_UID, uidlen, uidstr);
+ (void) strtol(uidstr, &endnum, 10);
+ if (*endnum != 0 || endnum == uidstr)
return (NSS_STR_PARSE_PARSE);
/*
* See discussion of private protocol in getbynam() above.
@@ -236,18 +205,8 @@ nis_object2ent(nobj, obj, argp)
* _nss_nisplus_getent(), but that's OK -- when we're doing
* enumerations we don't care what's in the argp->key union.
*/
- argp->key.uid = uid;
-
- /*
- * Default values
- */
- sp->sp_lstchg = -1;
- sp->sp_min = -1;
- sp->sp_max = -1;
- sp->sp_warn = -1;
- sp->sp_inact = -1;
- sp->sp_expire = -1;
- sp->sp_flag = 0;
+ if (strncmp(passwd, "*NP*", passwdlen) == 0)
+ be->flag = 1;
/*
* shadow information
@@ -256,67 +215,28 @@ nis_object2ent(nobj, obj, argp)
* with less than the desired number of ":" separated longs.
* XXX - should we be more strict ?
*/
- EC_SET(ecol, PW_NDX_SHADOW, len, val);
-
- if (len < 2)
- return (NSS_STR_PARSE_SUCCESS);
-
- /*
- * Parse val for the aging fields (quickly, they might die)
- */
-
- limit = val + len;
- p = val;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_lstchg = (int) x;
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_min = (int) x;
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_max = (int) x;
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_warn = (int) x;
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p) {
- sp->sp_inact = (int) x;
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, PW_NDX_SHADOW, shadowlen, shadow);
+
+ buflen = namelen + passwdlen + shadowlen + 3;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != ':' || endnum >= limit)
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_expire = (int) x;
- p = endnum + 1;
-
- x = strtol(p, &endnum, 10);
- if (*endnum != '\0' && *endnum != ':')
- return (NSS_STR_PARSE_SUCCESS);
- if (endnum != p)
- sp->sp_flag = (int) x;
-
+ (void) snprintf(buffer, buflen, "%s:%s:%s",
+ name, passwd, shadow);
+#ifdef DEBUG
+ (void) fprintf(stdout, "shadow [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -335,5 +255,5 @@ _nss_nisplus_shadow_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(sp_ops,
sizeof (sp_ops) / sizeof (sp_ops[0]),
- PW_TBLNAME, nis_object2ent));
+ PW_TBLNAME, nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/getuserattr.c b/usr/src/lib/nsswitch/nisplus/common/getuserattr.c
index 70b8a05e76..c6337373c7 100644
--- a/usr/src/lib/nsswitch/nisplus/common/getuserattr.c
+++ b/usr/src/lib/nsswitch/nisplus/common/getuserattr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -45,23 +44,20 @@ getbynam(nisplus_backend_ptr_t be, void *a)
/*
- * place the results from the nis_object structure into argp->buf.result
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
+/*ARGSUSED*/
static int
-nis_object2userstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
+nis_object2userstr(int nobj, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp)
{
- int len;
- int buflen = argp->buf.buflen;
- char *buffer, *limit, *val, *endnum, *nullstring;
- char *empty = "";
- userstr_t *user;
+ char *buffer, *name, *qual, *res1, *res2;
+ char *attr;
+ int buflen, namelen, quallen, res1len;
+ int res2len, attrlen;
struct entry_col *ecol;
- limit = argp->buf.buffer + buflen;
- user = (userstr_t *)argp->buf.result;
- buffer = argp->buf.buffer;
-
/*
* If we got more than one nis_object, we just ignore object(s)
* except the first. Although it should never have happened.
@@ -77,81 +73,42 @@ nis_object2userstr(int nobj, nis_object *obj, nss_XbyY_args_t *argp)
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * userstr->name: user name
- */
- EC_SET(ecol, USERATTR_NDX_NAME, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- user->name = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(user->name, val);
- nullstring = (buffer - 1);
-
- /*
- * userstr->qualifier: reserved for future use
- */
- EC_SET(ecol, USERATTR_NDX_QUALIFIER, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- user->qualifier = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(user->qualifier, val);
- nullstring = (buffer - 1);
-
- /*
- * userstr->res1: reserved field 1
- */
- EC_SET(ecol, USERATTR_NDX_RES1, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
+ /* user name */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, USERATTR_NDX_NAME, namelen, name);
+
+ /* qualifier: reserved for future use */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, USERATTR_NDX_QUALIFIER,
+ quallen, qual);
+
+ /* res1: reserved field 1 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, USERATTR_NDX_RES1, res1len, res1);
+
+ /* userstr->res2: reserved field 2 */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, USERATTR_NDX_RES2, res2len, res2);
+
+ /* attrs: key-value pairs of attributes */
+ __NISPLUS_GETCOL_OR_EMPTY(ecol, USERATTR_NDX_ATTR, attrlen, attr);
+
+ buflen = namelen + quallen + res1len + res2len + attrlen + 5;
+ if (argp->buf.result != NULL) {
+ if ((be->buffer = calloc(1, buflen)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ /* exclude trailing null from length */
+ be->buflen = buflen - 1;
+ buffer = be->buffer;
+ } else {
+ if (buflen > argp->buf.buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ buflen = argp->buf.buflen;
+ buffer = argp->buf.buffer;
+ (void) memset(buffer, 0, buflen);
}
- user->res1 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(user->res1, val);
- nullstring = (buffer - 1);
-
- /*
- * userstr->res2: reserved field 2
- */
- EC_SET(ecol, USERATTR_NDX_RES2, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- user->res2 = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(user->res2, val);
- nullstring = (buffer - 1);
-
- /*
- * userstr->attrs: key-value pairs of attributes
- */
- EC_SET(ecol, USERATTR_NDX_ATTR, len, val);
- if (len < 1 || (*val == '\0')) {
- val = empty;
- }
- user->attr = buffer;
- buffer += len;
- if (buffer >= limit) {
- return (NSS_STR_PARSE_ERANGE);
- }
- strcpy(user->attr, val);
- nullstring = (buffer - 1);
-
+ (void) snprintf(buffer, buflen, "%s:%s:%s:%s:%s",
+ name, qual, res1, res2, attr);
+#ifdef DEBUG
+ (void) fprintf(stdout, "userattr [%s]\n", buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -163,6 +120,7 @@ static nisplus_backend_op_t userattr_ops[] = {
getbynam
};
+/*ARGSUSED*/
nss_backend_t *
_nss_nisplus_user_attr_constr(const char *dummy1,
const char *dummy2,
diff --git a/usr/src/lib/nsswitch/nisplus/common/netmasks.c b/usr/src/lib/nsswitch/nisplus/common/netmasks.c
index 8e6ae5000c..308033514e 100644
--- a/usr/src/lib/nsswitch/nisplus/common/netmasks.c
+++ b/usr/src/lib/nsswitch/nisplus/common/netmasks.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,12 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus/netmasks.c -- "nisplus" backend for nsswitch "netmasks" database
- *
- * Copyright (c) 1996 Sun Microsystems Inc
- * All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -35,6 +36,8 @@
* dotted internet notation.
*/
+#include <stdlib.h>
+#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -49,29 +52,27 @@ getbynet(be, a)
nisplus_backend_ptr_t be;
void *a;
{
- nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
return (_nss_nisplus_lookup(be, argp, NETMASK_TAG_ADDR,
argp->key.name));
}
/*
- * Place the resulting struct inaddr from the nis_object structure into
- * argp->buf.result only if argp->buf.result is initialized (not NULL).
- *
+ * Convert nisplus object to files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*/
/*ARGSUSED*/
static int
-nis_object2ent(nobj, obj, argp)
- int nobj;
- nis_object *obj;
- nss_XbyY_args_t *argp;
+nis_object2str(nobj, obj, be, argp)
+ int nobj;
+ nis_object *obj;
+ nisplus_backend_ptr_t be;
+ nss_XbyY_args_t *argp;
{
- struct in_addr *mask = (struct in_addr *)argp->buf.result;
- char *val;
- struct in_addr addr;
- struct entry_col *ecol;
- int len;
+ char *mask;
+ int masklen;
+ struct in_addr addr;
+ struct entry_col *ecol;
/*
* If we got more than one nis_object, we just ignore it.
@@ -89,17 +90,22 @@ nis_object2ent(nobj, obj, argp)
ecol = obj->EN_data.en_cols.en_cols_val;
/* getnetmaskbynet */
- if (mask) {
- EC_SET(ecol, NETMASK_NDX_MASK, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- /* addr is an IPv4 address, therefore will always be 32bits */
- addr.s_addr = inet_addr(val);
- if (addr.s_addr == 0xffffffffL)
- return (NSS_STR_PARSE_PARSE);
- mask->s_addr = addr.s_addr;
- }
+ __NISPLUS_GETCOL_OR_RETURN(ecol, NETMASK_NDX_MASK, masklen, mask);
+ /* addr is an IPv4 address, therefore will always be 32bits */
+ addr.s_addr = inet_addr(mask);
+ if (addr.s_addr == INADDR_NONE)
+ return (NSS_STR_PARSE_PARSE);
+
+ /* exclude trailing null from length */
+ be->buflen = masklen;
+ if ((be->buffer = calloc(1, be->buflen + 1)) == NULL)
+ return (NSS_STR_PARSE_PARSE);
+ (void) strlcpy(be->buffer, mask, be->buflen + 1);
+#ifdef DEBUG
+ (void) fprintf(stdout, "netmasks [%s]\n", be->buffer);
+ (void) fflush(stdout);
+#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
@@ -115,5 +121,5 @@ _nss_nisplus_netmasks_constr(dummy1, dummy2, dummy3)
{
return (_nss_nisplus_constr(netmasks_ops,
sizeof (netmasks_ops) / sizeof (netmasks_ops[0]), NETMASK_TBLNAME,
- nis_object2ent));
+ nis_object2str));
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/nisplus_common.c b/usr/src/lib/nsswitch/nisplus/common/nisplus_common.c
index 51ad628f68..eec3fa9ada 100644
--- a/usr/src/lib/nsswitch/nisplus/common/nisplus_common.c
+++ b/usr/src/lib/nsswitch/nisplus/common/nisplus_common.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1991-1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
/*
@@ -35,6 +34,7 @@
#include "nisplus_common.h"
#include "nisplus_tables.h"
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <rpcsvc/nislib.h>
@@ -43,7 +43,7 @@
#define ORGDIR2 ".org_dir."
#define ORGDIRLEN 7
-extern u_int __nis_force_hard_lookups;
+extern uint_t __nis_force_hard_lookups;
extern int inet_pton(int, const char *, void *);
static nss_status_t
@@ -58,11 +58,13 @@ switch_err(nis_res)
case NIS_SUCCESS:
case NIS_S_SUCCESS:
case NIS_CBRESULTS:
+ errno = 0;
return (NSS_SUCCESS);
case NIS_NOTFOUND:
case NIS_PARTIAL:
case NIS_NOSUCHNAME:
+ errno = 0;
return (NSS_NOTFOUND);
case NIS_NAMEUNREACHABLE:
@@ -82,18 +84,21 @@ _nss_nisplus_list(name, extra_flags, res_p)
nis_result **res_p;
{
*res_p = nis_list((char *)name, NIS_LIST_COMMON | extra_flags |
- __nis_force_hard_lookups, 0, 0);
+ __nis_force_hard_lookups, 0, 0);
return (switch_err(*res_p));
}
-nss_status_t
+static nss_status_t
process_val(args, be, result)
- nss_XbyY_args_t *args;
+ nss_XbyY_args_t *args;
nisplus_backend_t *be;
- nis_result *result;
+ nis_result *result;
{
nss_status_t res;
- int parsestat;
+ int parsestat;
+
+ args->returnval = NULL;
+ args->returnlen = 0;
if ((res = switch_err(result)) != NSS_SUCCESS) {
return (res);
@@ -101,21 +106,71 @@ process_val(args, be, result)
if (NIS_RES_OBJECT(result) == 0) {
return (NSS_NOTFOUND);
}
- parsestat = (be->obj2ent)(NIS_RES_NUMOBJ(result),
- NIS_RES_OBJECT(result), args);
+ parsestat = (be->obj2str)(NIS_RES_NUMOBJ(result),
+ NIS_RES_OBJECT(result), be, args);
+ if (parsestat != NSS_STR_PARSE_SUCCESS)
+ goto fail;
+
+ /*
+ * If called by nscd's switch engine, the data
+ * is available in args->buf.buffer and there is
+ * no need to marshall it.
+ *
+ * Note for some dbs like ethers, the obj2str()
+ * routine will always put the NFF data in
+ * be->buffer because we cannot determine if
+ * we are inside nscd or inside the application.
+ */
+ if (args->buf.result == NULL && be->buffer == NULL) {
+ args->returnval = args->buf.buffer;
+ if (args->buf.buffer != NULL)
+ args->returnlen = strlen(args->buf.buffer);
+ return (NSS_SUCCESS);
+ }
+
+ /*
+ * If the data is in be->buffer it needs
+ * to be marshalled.
+ */
+ if (args->str2ent == NULL) {
+ parsestat = NSS_STR_PARSE_PARSE;
+ goto fail;
+ }
+ parsestat = (*args->str2ent)(be->buffer,
+ be->buflen,
+ args->buf.result,
+ args->buf.buffer,
+ args->buf.buflen);
if (parsestat == NSS_STR_PARSE_SUCCESS) {
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
args->returnval = args->buf.result;
- res = NSS_SUCCESS;
- } else if (parsestat == NSS_STR_PARSE_ERANGE) {
- args->returnval = 0;
+ if (args->buf.result != NULL)
+ args->returnlen = 1;
+ else if (args->buf.buffer != NULL) {
+ args->returnval = args->buf.buffer;
+ args->returnlen = strlen(args->buf.buffer);
+ }
+ return (NSS_SUCCESS);
+ }
+
+fail:
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
+ if (parsestat == NSS_STR_PARSE_ERANGE) {
args->erange = 1;
/* We won't find this otherwise, anyway */
- res = NSS_NOTFOUND;
+ return (NSS_NOTFOUND);
} else if (parsestat == NSS_STR_PARSE_PARSE) {
- args->returnval = 0;
- res = NSS_NOTFOUND;
+ return (NSS_NOTFOUND);
}
- return (res);
+ return (NSS_UNAVAIL);
}
nss_status_t
@@ -141,7 +196,7 @@ _nss_nisplus_lookup(be, argp, column_name, keyname)
/*
* Assumes that "keyname" is a null-terminated string.
*/
- sprintf(namebuf, "[%s=%s]%s", column_name, keyname,
+ (void) snprintf(namebuf, BUFSIZ, "[%s=%s]%s", column_name, keyname,
be->table_name);
r = nis_list(namebuf, NIS_LIST_COMMON | USE_DGRAM |
__nis_force_hard_lookups, 0, 0);
@@ -194,23 +249,23 @@ _nss_nisplus_expand_lookup(be, argp, column_name, keyname, table)
(directory[0] == '.' && directory[1] == '\0')) {
return (0);
}
- sprintf(namebuf, "[%s=", column_name);
+ (void) snprintf(namebuf, sizeof (namebuf), "[%s=", column_name);
if (strcmp(column_name, HOST_TAG_NAME) == 0) {
p = strchr(keyname, '.');
if (p == 0) {
- strcat(namebuf, keyname);
+ (void) strlcat(namebuf, keyname, sizeof (namebuf));
} else {
- strncat(namebuf, keyname, p - keyname);
+ (void) strncat(namebuf, keyname, p - keyname);
}
} else {
- strcat(namebuf, keyname);
+ (void) strlcat(namebuf, keyname, sizeof (namebuf));
p = 0;
}
- strcat(namebuf, "]");
- strcat(namebuf, table);
- strcat(namebuf, ORGDIR1);
+ (void) strlcat(namebuf, "]", sizeof (namebuf));
+ (void) strlcat(namebuf, table, sizeof (namebuf));
+ (void) strlcat(namebuf, ORGDIR1, sizeof (namebuf));
if (p != 0) {
- strcat(namebuf, p);
+ (void) strlcat(namebuf, p, sizeof (namebuf));
}
r = nis_list(namebuf, EXPAND_NAME | USE_DGRAM | NIS_LIST_COMMON |
__nis_force_hard_lookups, 0, 0);
@@ -222,45 +277,36 @@ _nss_nisplus_expand_lookup(be, argp, column_name, keyname, table)
}
nss_backend_t *
-_nss_nisplus_constr(ops, n_ops, tblname, obj2ent)
+_nss_nisplus_constr(ops, n_ops, tblname, obj2str)
nisplus_backend_op_t ops[];
int n_ops;
- const char *tblname; /* (Unqualified) name of */
- /* NIS+ table */
- nisplus_obj2ent_func obj2ent;
+ const char *tblname; /* (Unqualified) name of NIS+ table */
+ nisplus_obj2str_func obj2str;
{
const char *directory = nis_local_directory();
nisplus_backend_t *be;
#ifdef DEBUG
-fprintf(stderr, "Constructor called\n");
+ (void) fprintf(stdout, "Constructor called\n");
#endif /* DEBUG */
if (directory == 0 ||
(directory[0] == '.' && directory[1] == '\0') ||
- (be = (nisplus_backend_t *)malloc(sizeof (*be))) == 0) {
- return (0);
+ (be = (nisplus_backend_t *)calloc(1, sizeof (*be))) == 0) {
+ return (0);
}
- be->ops = ops;
- be->n_ops = n_ops;
-
- be->directory = directory;
- if ((be->table_name = (char *)malloc
- (strlen(tblname) + ORGDIRLEN + strlen(directory) + 3)) == 0)
+ be->ops = ops;
+ be->n_ops = n_ops;
+ be->directory = directory;
+ if ((be->table_name = (char *)malloc
+ (strlen(tblname) + ORGDIRLEN + strlen(directory) + 3)) == 0) {
+ free(be);
return (0);
- strcpy(be->table_name, tblname);
- strcat(be->table_name, ORGDIR2);
- strcat(be->table_name, directory);
-
- be->obj2ent = obj2ent;
- be->cursor.no.n_bytes = 0;
- be->cursor.no.n_len = 0;
- be->cursor.max_len = 0;
-
- /* this indicates that the path_list stuff is not initialized */
- be->path_list = 0;
- be->table_path = 0;
- be->path_index = 0;
+ }
+ (void) strcpy(be->table_name, tblname);
+ (void) strcat(be->table_name, ORGDIR2);
+ (void) strcat(be->table_name, directory);
+ be->obj2str = obj2str;
be->path_count = -1;
return ((nss_backend_t *)be);
@@ -274,10 +320,13 @@ _nss_nisplus_destr(be, dummy)
{
if (be != 0) {
/* === Should change to invoke ops[ENDENT] ? */
- _nss_nisplus_endent(be, 0);
+ (void) _nss_nisplus_endent(be, 0);
if (be->table_name != 0) {
free(be->table_name);
}
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ }
free(be);
}
return (NSS_SUCCESS); /* In case anyone is dumb enough to check */
@@ -310,7 +359,8 @@ nis_cursor_set_next(be, from)
be->cursor.no.n_bytes =
(char *)malloc(be->cursor.max_len);
}
- memcpy(be->cursor.no.n_bytes, from->n_bytes, from->n_len);
+ (void) memcpy(be->cursor.no.n_bytes, from->n_bytes,
+ from->n_len);
}
be->cursor.no.n_len = from->n_len;
}
@@ -367,6 +417,9 @@ _nss_nisplus_setent(be, dummy)
nis_result *res;
nis_object *tobj;
+ be->buffer = NULL;
+ be->buflen = 0;
+ be->flag = 0;
if (be->path_list == 0) {
res = nis_lookup(be->table_name, NIS_LIST_COMMON |
__nis_force_hard_lookups);
@@ -393,9 +446,9 @@ _nss_nisplus_setent(be, dummy)
nis_freeresult(res);
return (NSS_UNAVAIL);
}
- strcpy(table_name, tobj->zo_name);
- strcat(table_name, ".");
- strcat(table_name, tobj->zo_domain);
+ (void) strcpy(table_name, tobj->zo_name);
+ (void) strcat(table_name, ".");
+ (void) strcat(table_name, tobj->zo_domain);
/* save table path */
table_path = res->objects.objects_val[0].TA_data.ta_path;
@@ -423,7 +476,7 @@ _nss_nisplus_setent(be, dummy)
be->path_list[0] = table_name;
be->path_count = __nis_parse_path(be->table_path,
- &be->path_list[1], n - 1);
+ &be->path_list[1], (int)(n - 1));
be->path_count++; /* for entry at index 0 */
}
be->path_index = 0;
@@ -452,232 +505,73 @@ _nss_nisplus_endent(be, dummy)
free(be->path_list[0]);
free(be->path_list);
}
+ if (be->buffer != NULL) {
+ free(be->buffer);
+ be->buffer = NULL;
+ be->buflen = 0;
+ }
+ be->flag = 0;
be->table_path = 0;
be->path_list = 0;
be->path_index = 0;
be->path_count = -1;
- be->cursor.no.n_len = 0;
- be->cursor.max_len = 0;
+ be->cursor.no.n_len = 0;
+ be->cursor.max_len = 0;
return (NSS_SUCCESS);
}
-
-/*
- * returns NSS_STR_PARSE_PARSE if no aliases found.
- *
- * Overly loaded interface. Trying to do to many things using one common
- * code. Main purpose is to extract cname and aliases from NIS+ entry object(s)
- * for netdb databases: hosts, networks, protocols, rpc and services.
- *
- * hosts have always been special. We have special case code to deal with
- * multiple addresses. cnamep is overloaded to indicate this special case,
- * when NULL, otherwise it is set to point to the cname field in the caller's
- * structure to be populated.
- *
- * services are weird since they sometimes use 1-1/2 keys, e.g. name and proto
- * or port and proto. The NIS+ services table also has an extra column. The
- * special argument, proto, when non-NULL, serves the purpose of indicating
- * that we are parsing a services entry, and have specified the protocol which
- * must be used for screening. It is also non-NULL, and set to the proto field
- * of the first NIS+ entry by nis_obj2ent(), in case of enumeration on
- * services, and getservbyname/port calls where caller used a null proto,
- * which implies the caller can accept "any" protocol with the matching
- * name/port. The proto argument is NULL for all non-services searches.
- */
int
-netdb_aliases_from_nisobj(obj, nobj, proto, alias_list, aliaspp, cnamep, count)
- /* IN */
- nis_object *obj;
- int nobj;
- const char *proto;
- /* IN-OUT */
- char **alias_list; /* beginning of the buffer and alias vector */
- char **aliaspp; /* end of the buffer + 1 */
- char **cnamep;
- /* OUT */
- int *count; /* number of distinct aliases/address found */
-{
- return (__netdb_aliases_from_nisobj(obj, nobj, proto, alias_list,
- aliaspp, cnamep, count, 0));
-}
+nis_aliases_object2str(nis_object *obj, int nobj,
+ const char *cname, const char *protokey,
+ char *linep, char *limit) {
+ char *p, *name, *proto;
+ int cnamelen, namelen, protolen, protokeylen;
+ struct entry_col *ecol;
-int
-__netdb_aliases_from_nisobj(obj, nobj, proto, alias_list, aliaspp, cnamep,
- count, af_type)
- /* IN */
- nis_object *obj;
- int nobj;
- const char *proto;
- int af_type; /* address family for host mapping only */
- /* IN-OUT */
- char **alias_list; /* beginning of the buffer and alias vector */
- char **aliaspp; /* end of the buffer + 1 */
- char **cnamep;
- /* OUT */
- int *count; /* number of distinct aliases/address found */
-{
- int isaddr = (cnamep == 0);
+ cnamelen = strlen(cname);
+ protokeylen = (protokey) ? strlen(protokey) : 0;
- *count = 0;
- if ((char *)alias_list >= *aliaspp) {
- /*
- * Input condition not met. We must get a contiguous
- * area (alias_list, *aliaspp - 1).
- */
- return (NSS_STR_PARSE_PARSE);
- }
- for (/* */; nobj > 0; obj++, nobj--) {
- /*
- * in every iteration, pull the
- * address/alias/cname, copy it, set and update
- * the pointers vector if it is not a duplicate.
- */
- struct entry_col *ecol;
- char *val;
- int len;
+ /*
+ * process remaining entries
+ */
+ for (; nobj > 0; --nobj, obj++) {
+ /* object should be non-null */
+ if (obj == NULL)
+ return (NSS_STR_PARSE_PARSE);
if (obj->zo_data.zo_type != NIS_ENTRY_OBJ ||
- (obj->EN_data.en_cols.en_cols_len < NETDB_COL)) {
+ obj->EN_data.en_cols.en_cols_len < NETDB_COL) {
/* namespace/table/object is curdled */
return (NSS_STR_PARSE_PARSE);
}
ecol = obj->EN_data.en_cols.en_cols_val;
- /*
- * ASSUMPTION: cname and name field in NIS+ tables are
- * null terminated and the len includes the null char.
- */
- if (isaddr) {
- EC_SET(ecol, HOST_NDX_ADDR, len, val);
- } else {
+ if (protokey != NULL) {
+ /* skip if protocols doesn't match for services */
+ __NISPLUS_GETCOL_OR_RETURN(ecol, SERV_NDX_PROTO,
+ protolen, proto);
+ if (protolen != protokeylen ||
+ strncasecmp(proto, protokey, protolen) != 0)
+ continue;
+ }
- if (proto) {
- /*
- * indicates we screen for a desired proto
- * in the case of getservbyname/port()
- * with a non-null proto arg
- */
- EC_SET(ecol, SERV_NDX_PROTO, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- if (strcmp(proto, val) != 0)
- continue; /* ignore this entry */
- }
+ __NISPLUS_GETCOL_OR_CONTINUE(ecol, NETDB_NDX_NAME,
+ namelen, name);
- if (*cnamep == 0) {
- /* canonical name, hasn't been set so far */
- EC_SET(ecol, NETDB_NDX_CNAME, len, val);
- if (len < 2)
- return (NSS_STR_PARSE_PARSE);
- *aliaspp -= len;
- if (*aliaspp <=
- (char *)&(alias_list[*count + 1])) {
- /*
- * Has to be room for the pointer to
- * the name we're about to add, as
- * well as the final NULL ptr.
- */
- return (NSS_STR_PARSE_ERANGE);
- }
- memcpy(*aliaspp, val, len);
- *cnamep = *aliaspp;
- }
- EC_SET(ecol, NETDB_NDX_NAME, len, val);
- }
- if (len > 0) {
- int i;
- struct in6_addr addr6;
- struct in_addr addr;
-
- if (isaddr) { /* special case for host addresses */
-
- if (af_type == AF_INET) {
- if (inet_pton(AF_INET, val,
- (void *) &addr) != 1)
- continue; /* skip entry */
- } else {
- /*
- * We now allow IPv4 and IPv6 addrs in the
- * ipnodes table. If found, convert it to a
- * v4 mapped IPv6 address.
- */
- if (inet_pton(AF_INET6, val,
- (void *) &addr6) != 1) {
- if (inet_pton(AF_INET, val,
- (void *) &addr) != 1) {
- continue;
- /* skip entry */
- } else {
- IN6_INADDR_TO_V4MAPPED(
- &addr,
- &addr6);
- }
- }
- }
-
- /* Check for duplicate address */
- for (i = 0; i < *count; i++) {
- if (af_type == AF_INET) {
- if (memcmp(alias_list[i], &addr,
- sizeof (struct in_addr))
- == 0) {
- goto next_obj;
- }
- } else {
- if (memcmp(alias_list[i],
- &addr6,
- sizeof (struct in6_addr))
- == 0) {
- goto next_obj;
- }
- }
- }
- /*
- * Hope nobody treats an h_addr_list[i] as a
- * null terminated string. We are not storing
- * that here.
- */
- if (af_type == AF_INET)
- *aliaspp -= sizeof (struct in_addr);
- else
- *aliaspp -= sizeof (struct in6_addr);
- } else {
- /* Check for duplicate alias */
- for (i = 0; i < *count; i++) {
- if (strcmp(alias_list[i], val) == 0) {
- goto next_obj;
- }
- }
- *aliaspp -= len;
- }
- alias_list[i] = *aliaspp;
- if (*aliaspp <= (char *)&(alias_list[i + 1])) {
- /*
- * Has to be room for the pointer to
- * the address we're about to add, as
- * well as the final NULL ptr.
- */
+ /*
+ * add the "name" to the list if it doesn't
+ * match the "cname"
+ */
+ if (cnamelen != namelen ||
+ strncmp(name, cname, namelen) != 0) {
+ p = linep + 1 + namelen;
+ if (p >= limit)
return (NSS_STR_PARSE_ERANGE);
- }
- if (isaddr) {
- if (af_type == AF_INET)
- memcpy(alias_list[i], (char *)&addr,
- sizeof (struct in_addr));
- else
- memcpy(alias_list[i], (char *)&addr6,
- sizeof (struct in6_addr));
- } else {
- memcpy(*aliaspp, val, len);
- }
- ++(*count);
+ (void) snprintf(linep, (size_t)(limit - linep),
+ " %s", name);
+ linep = p;
}
- next_obj:
- ;
}
- alias_list[*count] = NULL;
- if (*count == 0)
- return (NSS_STR_PARSE_PARSE);
- else
- return (NSS_STR_PARSE_SUCCESS);
+ return (NSS_STR_PARSE_SUCCESS);
}
diff --git a/usr/src/lib/nsswitch/nisplus/common/nisplus_common.h b/usr/src/lib/nsswitch/nisplus/common/nisplus_common.h
index 6e8bfac6ff..5c6ae11c8c 100644
--- a/usr/src/lib/nsswitch/nisplus/common/nisplus_common.h
+++ b/usr/src/lib/nsswitch/nisplus/common/nisplus_common.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,97 +37,101 @@
/*
* We want these flags turned on in all nis_list() requests that we perform;
- * other flags (USE_DGRAM, EXPAND_NAME) are only wanted for some requests.
+ * other flags (USE_DGRAM, EXPAND_NAME) are only wanted for some requests.
*/
#define NIS_LIST_COMMON (FOLLOW_LINKS | FOLLOW_PATH)
typedef struct nisplus_backend *nisplus_backend_ptr_t;
typedef nss_status_t (*nisplus_backend_op_t)(nisplus_backend_ptr_t, void *);
-typedef int (*nisplus_obj2ent_func)(int nobjs,
- nis_object *obj,
- nss_XbyY_args_t *arg);
+typedef int (*nisplus_obj2str_func)(int nobjs, nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *arg);
struct nisplus_backend {
nisplus_backend_op_t *ops;
nss_dbop_t n_ops;
- const char *directory; /* fully qualified directory */
- /* name */
- char *table_name;
+ const char *directory; /* fully qualified directory */
+
/*
* table_name is fully qualified (includes org_dir and
* directory name) and cached here using one time malloc.
*/
- nisplus_obj2ent_func obj2ent;
+ char *table_name;
+
+ nisplus_obj2str_func obj2str;
struct {
- struct netobj no;
- u_int max_len;
- } cursor;
+ struct netobj no;
+ uint_t max_len;
+ } cursor;
- /*
+ /*
* Fields for handling table paths during enumeration.
* The path_list field is allocated dynamically because
* it is kind of big and most applications don't do
* enumeration.
*/
- char *table_path;
- int path_index;
- int path_count;
- nis_name *path_list;
+ char *table_path;
+ int path_index;
+ int path_count;
+ nis_name *path_list;
+
+ /*
+ * Internal fields to support NSS2 format
+ */
+ char *buffer;
+ int buflen;
+ uint8_t flag;
};
typedef struct nisplus_backend nisplus_backend_t;
#if defined(__STDC__)
-extern nss_backend_t *_nss_nisplus_constr (nisplus_backend_op_t *ops,
- int n_ops,
- const char *rdn,
- nisplus_obj2ent_func func);
-extern nss_status_t _nss_nisplus_destr (nisplus_backend_ptr_t,
+extern nss_backend_t *_nss_nisplus_constr(nisplus_backend_op_t *ops,
+ int n_ops,
+ const char *rdn,
+ nisplus_obj2str_func func);
+extern nss_status_t _nss_nisplus_destr(nisplus_backend_ptr_t,
void *dummy);
-extern nss_status_t _nss_nisplus_setent (nisplus_backend_ptr_t,
+extern nss_status_t _nss_nisplus_setent(nisplus_backend_ptr_t,
void *dummy);
-extern nss_status_t _nss_nisplus_endent (nisplus_backend_ptr_t,
+extern nss_status_t _nss_nisplus_endent(nisplus_backend_ptr_t,
void *dummy);
-extern nss_status_t _nss_nisplus_getent (nisplus_backend_ptr_t,
- void *arg);
-extern nss_status_t _nss_nisplus_lookup (nisplus_backend_ptr_t,
+extern nss_status_t _nss_nisplus_getent(nisplus_backend_ptr_t,
+ void *arg);
+extern nss_status_t _nss_nisplus_lookup(nisplus_backend_ptr_t,
nss_XbyY_args_t *arg,
- const char *key,
- const char *val);
-extern nss_status_t _nss_nisplus_expand_lookup (nisplus_backend_ptr_t,
+ const char *key,
+ const char *val);
+extern nss_status_t _nss_nisplus_expand_lookup(nisplus_backend_ptr_t,
nss_XbyY_args_t *arg,
- const char *key,
- const char *val,
- const char *table);
-extern int netdb_aliases_from_nisobj(nis_object *obj,
- int nobj,
- const char *proto,
- char **alias_list,
- char **aliaspp,
- char **cnamep,
- int *count);
-extern int __netdb_aliases_from_nisobj(nis_object *obj,
+ const char *key,
+ const char *val,
+ const char *table);
+extern int nis_aliases_object2str(nis_object *obj,
int nobj,
+ const char *cname,
const char *proto,
- char **alias_list,
- char **aliaspp,
- char **cnamep,
- int *count,
- int af_type);
+ char *linep,
+ char *limit);
+extern int nis_hosts_object2str(int nobj,
+ nis_object *obj,
+ nisplus_backend_ptr_t be,
+ nss_XbyY_args_t *argp,
+ int af);
#else /* __STDC__ */
extern nss_backend_t *_nss_nisplus_constr();
-extern nss_status_t _nss_nisplus_destr ();
+extern nss_status_t _nss_nisplus_destr();
extern nss_status_t _nss_nisplus_setent();
extern nss_status_t _nss_nisplus_endent();
extern nss_status_t _nss_nisplus_getent();
-extern nss_status_t _nss_nisplus_lookup ();
+extern nss_status_t _nss_nisplus_lookup();
extern nss_status_t _nss_nisplus__expand_lookup();
extern int build_aliases_from_nisobj();
#endif /* __STDC__ */
/* Lower-level interface */
-extern nss_status_t _nss_nisplus_list(const char *name,
- int extra_flags,
- nis_result **r);
+extern nss_status_t _nss_nisplus_list(const char *name,
+ int extra_flags,
+ nis_result **r);
extern int __nis_parse_path();
extern int _thr_main(void);
extern int __nss2herrno();
diff --git a/usr/src/lib/nsswitch/nisplus/common/nisplus_tables.h b/usr/src/lib/nsswitch/nisplus/common/nisplus_tables.h
index 7f3823e985..a9f53fd00c 100644
--- a/usr/src/lib/nsswitch/nisplus/common/nisplus_tables.h
+++ b/usr/src/lib/nsswitch/nisplus/common/nisplus_tables.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,10 +19,12 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* nisplus_tables.h
- *
- * Copyright (c) 1988-2000 by Sun Microsystems, Inc.
- * All rights reserved.
*/
#ifndef _NISPLUS_TABLES_H
@@ -302,6 +303,30 @@ extern "C" {
#define EC_SET(ecp, ndx, l, v) \
((l) = EC_LEN(ecp, ndx), (v) = EC_VAL(ecp, ndx))
+#define __NISPLUS_GETCOL_OR_EMPTY(ecp, ndx, l, v) \
+ EC_SET(ecp, ndx, l, v);\
+ if (l < 2) {\
+ (v) = "";\
+ (l) = 1;\
+ } else {\
+ l--;\
+ }
+
+#define __NISPLUS_GETCOL_OR_RETURN(ecp, ndx, l, v) \
+ EC_SET(ecp, ndx, l, v);\
+ if (l < 2) {\
+ return (NSS_STR_PARSE_PARSE);\
+ } else {\
+ l--;\
+ }
+
+#define __NISPLUS_GETCOL_OR_CONTINUE(ecp, ndx, l, v) \
+ EC_SET(ecp, ndx, l, v);\
+ if (l < 2) {\
+ continue;\
+ } else {\
+ l--;\
+ }
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/nsswitch/user/Makefile.com b/usr/src/lib/nsswitch/user/Makefile.com
index c51cc34604..df1c209dfc 100644
--- a/usr/src/lib/nsswitch/user/Makefile.com
+++ b/usr/src/lib/nsswitch/user/Makefile.com
@@ -39,6 +39,8 @@ include ../../Makefile.com
include ../../../Makefile.rootfs
CPPFLAGS += -I../../../common/inc
+LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2 -erroff=E_FUNC_SET_NOT_USED
+LINTFLAGS64 += -erroff=E_GLOBAL_COULD_BE_STATIC2 -erroff=E_FUNC_SET_NOT_USED
DYNLIB1 = nss_user.so$(VERS)
diff --git a/usr/src/lib/nsswitch/user/common/getprinter.c b/usr/src/lib/nsswitch/user/common/getprinter.c
index 25bc1ac49d..7e62b69724 100644
--- a/usr/src/lib/nsswitch/user/common/getprinter.c
+++ b/usr/src/lib/nsswitch/user/common/getprinter.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* "user" backend for nsswitch "printers" database. This module implements
@@ -95,6 +94,7 @@ _nss_user_printers_convert(char *entry, nss_XbyY_args_t *args)
* backends don't include it in the data passed to the backend. For this
* reason, we process everything here and don't bother calling the backend.
*/
+/*ARGSUSED*/
static nss_status_t
_nss_user_XY_printers(be, args, filter)
user_backend_ptr_t be;
@@ -107,7 +107,6 @@ _nss_user_XY_printers(be, args, filter)
*/
{
nss_status_t res;
- int parsestat;
int namelen;
if (be->buf == 0 &&
@@ -119,12 +118,12 @@ _nss_user_XY_printers(be, args, filter)
res = NSS_NOTFOUND;
namelen = strlen(args->key.name);
+ /*CONSTCOND*/
while (1) {
char *instr = be->buf;
char *p, *limit;
int linelen;
int found = 0;
- char *key, *value;
/*
* _nss_user_read_line does process the '\' that are used
@@ -194,6 +193,7 @@ getent(be, a)
res = NSS_NOTFOUND;
+ /*CONSTCOND*/
while (1) {
char *instr = be->buf;
int linelen;
@@ -240,6 +240,7 @@ static user_backend_op_t printers_ops[] = {
getbyname
};
+/*ARGSUSED*/
nss_backend_t *
_nss_user_printers_constr(dummy1, dummy2, dummy3)
const char *dummy1, *dummy2, *dummy3;
@@ -248,7 +249,7 @@ _nss_user_printers_constr(dummy1, dummy2, dummy3)
if ((home = getenv("HOME")) == NULL)
home = "";
- snprintf(path, sizeof (path), "%s/.printers", home);
+ (void) snprintf(path, sizeof (path), "%s/.printers", home);
return (_nss_user_constr(printers_ops,
sizeof (printers_ops) / sizeof (printers_ops[0]),
diff --git a/usr/src/lib/nsswitch/user/common/user_common.c b/usr/src/lib/nsswitch/user/common/user_common.c
index 1a52140be3..76a7aa9872 100644
--- a/usr/src/lib/nsswitch/user/common/user_common.c
+++ b/usr/src/lib/nsswitch/user/common/user_common.c
@@ -43,6 +43,7 @@
#include <sys/stat.h>
#include <string.h>
+/*ARGSUSED*/
nss_status_t
_nss_user_setent(be, dummy)
user_backend_ptr_t be;
@@ -62,13 +63,14 @@ _nss_user_setent(be, dummy)
return (NSS_SUCCESS);
}
+/*ARGSUSED*/
nss_status_t
_nss_user_endent(be, dummy)
user_backend_ptr_t be;
void *dummy;
{
if (be->f != 0) {
- fclose(be->f);
+ (void) fclose(be->f);
be->f = 0;
}
if (be->buf != 0) {
@@ -98,6 +100,7 @@ _nss_user_read_line(f, buffer, buflen)
int linelen; /* 1st unused slot in buffer */
int c;
+ /*CONSTCOND*/
while (1) {
linelen = 0;
while (linelen < buflen - 1) { /* "- 1" saves room for \n\0 */
@@ -168,6 +171,7 @@ _nss_user_XY_all(be, args, netdb, filter, check)
res = NSS_NOTFOUND;
+ /*CONSTCOND*/
while (1) {
char *instr = be->buf;
int linelen;
@@ -250,6 +254,7 @@ _nss_user_XY_all(be, args, netdb, filter, check)
}
+/*ARGSUSED*/
nss_status_t
_nss_user_destr(be, dummy)
user_backend_ptr_t be;
@@ -257,7 +262,7 @@ _nss_user_destr(be, dummy)
{
if (be != 0) {
if (be->f != 0) {
- _nss_user_endent(be, 0);
+ (void) _nss_user_endent(be, 0);
}
free((char *)be->filename);
free(be);
diff --git a/usr/src/lib/print/libprint/common/nss_printer.c b/usr/src/lib/print/libprint/common/nss_printer.c
index f84fbb3b64..252e4e6297 100644
--- a/usr/src/lib/print/libprint/common/nss_printer.c
+++ b/usr/src/lib/print/libprint/common/nss_printer.c
@@ -64,7 +64,7 @@ _nss_initf_printers(p)
/* regular behaviour */
p->name = NSS_DBNAM_PRINTERS; /* "printers" */
p->default_config = NSS_DEFCONF_PRINTERS;
- initialized = 1;
+ /* keep reinitializing as needed was: initialized = 1; */
}
syslog(LOG_DEBUG, "database: %s, services: %s",
(p->name ? p->name : "NULL"),