4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
33 #include <sys/param.h>
36 #include "ns_cache_door.h"
39 #if defined(PIC) || defined(lint)
43 * Routines that actually performs the door call.
44 * Note that we cache a file descriptor. We do
45 * the following to prevent disasters:
47 * 1) Never use 0,1 or 2; if we get this from the open
50 * 2) Set the close on exec flags so descriptor remains available
53 * 3) Verify that the door is still the same one we had before
54 * by using door_info on the client side.
56 * Note that we never close the file descriptor if it isn't one
57 * we allocated; we check this with door info. The rather tricky
58 * logic is designed to be fast in the normal case (fd is already
59 * allocated and is ok) while handling the case where the application
60 * closed it underneath us or where the nscd dies or re-execs itself
61 * and we're a multi-threaded application. Note that we cannot protect
62 * the application if it closes the fd and it is multi-threaded.
64 * int _cache_trydoorcall(void *dptr, int *bufsize, int *actualsize);
66 * *dptr IN: points to arg buffer OUT: points to results buffer
67 * *bufsize IN: overall size of buffer OUT: overall size of buffer
68 * *actualsize IN: size of call data OUT: size of return data
70 * Note that *dptr may change if provided space as defined by *bufsize is
71 * inadequate. In this case the door call mmaps more space and places
72 * the answer there and sets dptr to contain a pointer to the space, which
73 * should be freed with munmap.
75 * Returns 0 if the door call reached the server, -1 if contact was not made.
80 static mutex_t _door_lock
= DEFAULTMUTEX
;
81 static int doorfd
= -1;
84 * This function does the first part: ensures a file descriptor is
88 __ns_ldap_trydoorcall_getfd()
90 static door_info_t real_door
;
94 * the first time in we try and open and validate the door.
95 * the validations are that the door must have been
96 * created with the name service door cookie and
97 * that the file attached to the door is owned by root
98 * and readonly by user, group and other. If any of these
99 * validations fail we refuse to use the door.
102 (void) mutex_lock(&_door_lock
);
110 if ((doorfd
= open(LDAP_CACHE_DOOR
, O_RDONLY
, 0))
112 (void) mutex_unlock(&_door_lock
);
113 return (NS_CACHE_NOSERVER
);
117 * dup up the file descriptor if we have 0 - 2
118 * to avoid problems with shells stdin/out/err
122 while (doorfd
< 3) { /* we have a reserved fd */
124 if ((doorfd
= dup(doorfd
)) < 0) {
126 (void) close(tbc
[i
]);
128 (void) mutex_unlock(&_door_lock
);
129 return (NS_CACHE_NOSERVER
);
134 (void) close(tbc
[i
]);
137 * mark this door descriptor as close on exec
139 (void) fcntl(doorfd
, F_SETFD
, FD_CLOEXEC
);
140 if (door_info(doorfd
, &real_door
) == -1 ||
141 (real_door
.di_attributes
& DOOR_REVOKED
) ||
142 real_door
.di_data
!= (uintptr_t)LDAP_CACHE_DOOR_COOKIE
) {
144 * we should close doorfd because we just opened it
146 (void) close(doorfd
);
148 (void) mutex_unlock(&_door_lock
);
149 return (NS_CACHE_NOSERVER
);
152 if (door_info(doorfd
, &my_door
) == -1 ||
153 my_door
.di_data
!= (uintptr_t)LDAP_CACHE_DOOR_COOKIE
||
154 my_door
.di_uniquifier
!= real_door
.di_uniquifier
) {
157 * someone else has clobbered fd
163 if (my_door
.di_attributes
& DOOR_REVOKED
) {
164 (void) close(doorfd
);
165 doorfd
= -1; /* try and restart connection */
170 (void) mutex_unlock(&_door_lock
);
171 return (NS_CACHE_SUCCESS
);
175 * This function does the second part: sends a door request to
176 * the ldap_cachemgr daemon.
179 __ns_ldap_trydoorcall_send(ldap_data_t
**dptr
, int *ndata
, int *adata
)
183 param
.rbuf
= (char *)*dptr
;
184 param
.rsize
= *ndata
;
185 param
.data_ptr
= (char *)*dptr
;
186 param
.data_size
= *adata
;
187 param
.desc_ptr
= NULL
;
189 if (door_call(doorfd
, ¶m
) == -1) {
190 return (NS_CACHE_NOSERVER
);
192 *adata
= (int)param
.data_size
;
193 *ndata
= (int)param
.rsize
;
194 *dptr
= (ldap_data_t
*)param
.data_ptr
;
195 if (*adata
== 0 || *dptr
== NULL
) {
196 return (NS_CACHE_NOSERVER
);
199 return ((*dptr
)->ldap_ret
.ldap_return_code
);
203 * This function does part 1 and 2: makes sure a file descriptor is
204 * available and sends a door request to the ldap_cachemgr daemon.
207 __ns_ldap_trydoorcall(ldap_data_t
**dptr
, int *ndata
, int *adata
)
211 if ((rc
= __ns_ldap_trydoorcall_getfd()) == NS_CACHE_SUCCESS
)
212 return (__ns_ldap_trydoorcall_send(dptr
, ndata
, adata
));
218 __ns_ldap_doorfd_close()
220 (void) mutex_lock(&_door_lock
);
222 (void) close(doorfd
);
224 (void) mutex_unlock(&_door_lock
);
228 * routine to check if server is already running
232 __ns_ldap_cache_ping()
239 data
.ldap_call
.ldap_callnumber
= NULLCALL
;
240 ndata
= sizeof (data
);
241 adata
= sizeof (data
);
243 return (__ns_ldap_trydoorcall(&dptr
, &ndata
, &adata
));