dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libldap5 / sources / ldap / prldap / ldappr-dns.c
blob7fb39615c7a1be5c0edb4571b81b3f5d0f5f8a7e
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
7 /*
8 * The contents of this file are subject to the Netscape Public
9 * License Version 1.1 (the "License"); you may not use this file
10 * except in compliance with the License. You may obtain a copy of
11 * the License at http://www.mozilla.org/NPL/
13 * Software distributed under the License is distributed on an "AS
14 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
18 * The Original Code is Mozilla Communicator client code, released
19 * March 31, 1998.
21 * The Initial Developer of the Original Code is Netscape
22 * Communications Corporation. Portions created by Netscape are
23 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
24 * Rights Reserved.
26 * Contributor(s):
30 * DNS callback functions for libldap that use the NSPR (Netscape
31 * Portable Runtime) thread API.
35 #ifdef _SOLARIS_SDK
36 #include "solaris-int.h"
37 #include <libintl.h>
38 #include <syslog.h>
39 #include <nsswitch.h>
40 #include <synch.h>
41 #include <nss_dbdefs.h>
42 #include <netinet/in.h>
43 static char *host_service = NULL;
44 static DEFINE_NSS_DB_ROOT(db_root_hosts);
45 #endif
47 #include "ldappr-int.h"
49 static LDAPHostEnt *prldap_gethostbyname( const char *name,
50 LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
51 void *extradata );
52 static LDAPHostEnt *prldap_gethostbyaddr( const char *addr, int length,
53 int type, LDAPHostEnt *result, char *buffer, int buflen,
54 int *statusp, void *extradata );
55 static int prldap_getpeername( LDAP *ld, struct sockaddr *addr,
56 char *buffer, int buflen );
57 static LDAPHostEnt *prldap_convert_hostent( LDAPHostEnt *ldhp,
58 PRHostEnt *prhp );
60 #ifdef _SOLARIS_SDK
61 static LDAPHostEnt *
62 prldap_gethostbyname1(const char *name, LDAPHostEnt *result,
63 char *buffer, int buflen, int *statusp, void *extradata);
64 extern int
65 str2hostent(const char *instr, int lenstr, void *ent, char *buffer,
66 int buflen);
67 #endif /* _SOLARIS_SDK */
71 * Install NSPR DNS functions into ld (if ld is NULL, they are installed
72 * as the default functions for new LDAP * handles).
74 * Returns 0 if all goes well and -1 if not.
76 int
77 prldap_install_dns_functions( LDAP *ld )
79 struct ldap_dns_fns dnsfns;
81 memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) );
82 dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
83 dnsfns.lddnsfn_gethostbyname = prldap_gethostbyname;
84 dnsfns.lddnsfn_gethostbyaddr = prldap_gethostbyaddr;
85 dnsfns.lddnsfn_getpeername = prldap_getpeername;
86 if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) != 0 ) {
87 return( -1 );
90 return( 0 );
94 static LDAPHostEnt *
95 prldap_gethostbyname( const char *name, LDAPHostEnt *result,
96 char *buffer, int buflen, int *statusp, void *extradata )
98 PRHostEnt prhent;
100 if( !statusp || ( *statusp = (int)PR_GetIPNodeByName( name,
101 PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT,
102 buffer, buflen, &prhent )) == PR_FAILURE ) {
103 return( NULL );
106 return( prldap_convert_hostent( result, &prhent ));
110 static LDAPHostEnt *
111 prldap_gethostbyaddr( const char *addr, int length, int type,
112 LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
113 void *extradata )
115 PRHostEnt prhent;
116 PRNetAddr iaddr;
118 if ( PR_SetNetAddr(PR_IpAddrNull, PRLDAP_DEFAULT_ADDRESS_FAMILY,
119 0, &iaddr) == PR_FAILURE
120 || PR_StringToNetAddr( addr, &iaddr ) == PR_FAILURE ) {
121 return( NULL );
124 if( !statusp || (*statusp = PR_GetHostByAddr(&iaddr, buffer,
125 buflen, &prhent )) == PR_FAILURE ) {
126 return( NULL );
128 return( prldap_convert_hostent( result, &prhent ));
131 static int
132 prldap_getpeername( LDAP *ld, struct sockaddr *addr, char *buffer, int buflen)
134 PRLDAPIOSocketArg *sa;
135 PRFileDesc *fd;
136 PRNetAddr iaddr;
137 int ret;
139 if (NULL != ld) {
140 ret = prldap_socket_arg_from_ld( ld, &sa );
141 if (ret != LDAP_SUCCESS) {
142 return (-1);
144 ret = PR_GetPeerName(sa->prsock_prfd, &iaddr);
145 if( ret == PR_FAILURE ) {
146 return( -1 );
148 *addr = *((struct sockaddr *)&iaddr.raw);
149 ret = PR_NetAddrToString(&iaddr, buffer, buflen);
150 if( ret == PR_FAILURE ) {
151 return( -1 );
153 return (0);
155 return (-1);
160 * Function: prldap_convert_hostent()
161 * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt
162 * Returns: the LDAPHostEnt pointer passed in.
164 static LDAPHostEnt *
165 prldap_convert_hostent( LDAPHostEnt *ldhp, PRHostEnt *prhp )
167 ldhp->ldaphe_name = prhp->h_name;
168 ldhp->ldaphe_aliases = prhp->h_aliases;
169 ldhp->ldaphe_addrtype = prhp->h_addrtype;
170 ldhp->ldaphe_length = prhp->h_length;
171 ldhp->ldaphe_addr_list = prhp->h_addr_list;
172 return( ldhp );
175 #ifdef _SOLARIS_SDK
177 * prldap_x_install_dns_skipdb attempts to prevent recursion in resolving
178 * the hostname to an IP address when a host name is given to LDAP user.
180 * For example, libsldap cannot use LDAP to resolve the host name to an
181 * address because of recursion. The caller is instructing libldap to skip
182 * the specified name service when resolving addresses for the specified
183 * ldap connection.
185 * Note:
186 * This only supports ipv4 addresses currently.
188 * Since host_service applies to all connections, calling
189 * prldap_x_install_dns_skipdb with name services other than
190 * ldap or what uses ldap (for example nis+ might use ldap) to
191 * skip will lead to unpredictable results.
193 * Returns:
194 * 0 if success and data base found
195 * -1 if failure
199 prldap_x_install_dns_skipdb(LDAP *ld, const char *skip)
201 enum __nsw_parse_err pserr;
202 struct __nsw_switchconfig *conf;
203 struct __nsw_lookup *lkp;
204 struct ldap_dns_fns dns_fns;
205 char *name_list = NULL;
206 char *tmp;
207 const char *name;
208 int len;
209 boolean_t got_skip = B_FALSE;
212 * db_root_hosts.lock mutex is used to ensure that the name list
213 * is not in use by the name service switch while we are updating
214 * the host_service
217 (void) mutex_lock(&db_root_hosts.lock);
218 conf = __nsw_getconfig("hosts", &pserr);
219 if (conf == NULL) {
220 (void) mutex_unlock(&db_root_hosts.lock);
221 return (0);
224 /* check for skip and count other backends */
225 for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
226 name = lkp->service_name;
227 if (strcmp(name, skip) == 0) {
228 got_skip = B_TRUE;
229 continue;
231 if (name_list == NULL)
232 name_list = strdup(name);
233 else {
234 len = strlen(name_list);
235 tmp = realloc(name_list, len + strlen(name) + 2);
236 if (tmp == NULL) {
237 free(name_list);
238 name_list = NULL;
239 } else {
240 name_list = tmp;
241 name_list[len++] = ' ';
242 (void) strcpy(name_list+len, name);
245 if (name_list == NULL) { /* alloc error */
246 (void) mutex_unlock(&db_root_hosts.lock);
247 __nsw_freeconfig(conf);
248 return (-1);
251 __nsw_freeconfig(conf);
252 if (!got_skip) {
254 * Since skip name service not used for hosts, we do not need
255 * to install our private address resolution function
257 (void) mutex_unlock(&db_root_hosts.lock);
258 free(name_list);
259 return (0);
261 free(host_service);
262 host_service = name_list;
263 (void) mutex_unlock(&db_root_hosts.lock);
265 if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
266 return (-1);
267 dns_fns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
268 dns_fns.lddnsfn_gethostbyname = prldap_gethostbyname1;
269 if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
270 return (-1);
271 return (0);
275 * prldap_initf_hosts is passed to and called by nss_search() as a
276 * service routine.
278 * Returns:
279 * None
282 static void
283 prldap_initf_hosts(nss_db_params_t *p)
285 static char *no_service = "";
287 p->name = NSS_DBNAM_HOSTS;
288 p->flags |= NSS_USE_DEFAULT_CONFIG;
289 p->default_config = host_service == NULL ? no_service : host_service;
293 * called by prldap_gethostbyname1()
296 * prldap_switch_gethostbyname_r is called by prldap_gethostbyname1 as a
297 * substitute for gethostbyname_r(). A method which prevents recursion. see
298 * prldap_gethostbyname1() and prldap_x_install_dns_skipdb().
300 * Returns:
301 * PR_SUCCESS if success
302 * PR_FAILURE if failure
305 static int
306 prldap_switch_gethostbyname_r(const char *name,
307 struct hostent *result, char *buffer, int buflen,
308 int *h_errnop)
310 nss_XbyY_args_t arg;
311 nss_status_t res;
312 struct hostent *resp;
315 * Log the information indicating that we are trying to
316 * resolve the LDAP server name.
318 syslog(LOG_INFO, "libldap: Resolving server name \"%s\"", name);
320 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent);
322 arg.key.name = name;
323 arg.stayopen = 0;
325 res = nss_search(&db_root_hosts, prldap_initf_hosts,
326 NSS_DBOP_HOSTS_BYNAME, &arg);
327 arg.status = res;
328 *h_errnop = arg.h_errno;
329 resp = (struct hostent *)NSS_XbyY_FINI(&arg);
331 return (resp != NULL ? PR_SUCCESS : PR_FAILURE);
335 * prldap_gethostbyname1 is used to be a substitute gethostbyname_r for
336 * libldap when it is unsafe to use the normal nameservice functions.
338 * Returns:
339 * pointer to LDAPHostEnt: if success contains the address
340 * NULL pointer: if failure
343 static LDAPHostEnt *
344 prldap_gethostbyname1(const char *name, LDAPHostEnt *result,
345 char *buffer, int buflen, int *statusp, void *extradata)
347 int h_errno;
348 LDAPHostEnt prhent;
350 memset(&prhent, '\0', sizeof (prhent));
351 if (!statusp || ( *statusp = prldap_switch_gethostbyname_r(name,
352 &prhent, buffer, buflen, &h_errno )) == PR_FAILURE) {
354 * If we got here, it means that we are not able to
355 * resolve the LDAP server name and so warn the system
356 * adminstrator accordingly.
358 syslog(LOG_WARNING, "libldap: server name \"%s\" could not "
359 "be resolved", name);
360 return (NULL);
363 return (prldap_convert_hostent(result, &prhent));
366 #endif /* _SOLARIS_SDK */