xref: /titanic_54/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c (revision 36e852a172cba914383d7341c988128b2c667fbd)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*36e852a1SRaja Andra  * Common Development and Distribution License (the "License").
6*36e852a1SRaja Andra  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*36e852a1SRaja Andra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*36e852a1SRaja Andra  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifdef SLP
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * This file contains all the dynamic server discovery functionality
307c478bd9Sstevel@tonic-gate  * for ldap_cachemgr. SLP is used to query the network for any changes
317c478bd9Sstevel@tonic-gate  * in the set of deployed LDAP servers.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * The algorithm used is outlined here:
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  *   1. Find all naming contexts with SLPFindAttrs. (See
367c478bd9Sstevel@tonic-gate  *      find_all_contexts())
377c478bd9Sstevel@tonic-gate  *   2. For each context, find all servers which serve that context
387c478bd9Sstevel@tonic-gate  *      with SLPFindSrvs. (See foreach_context())
397c478bd9Sstevel@tonic-gate  *   3. For each server, retrieve that server's attributes with
407c478bd9Sstevel@tonic-gate  *      SLPFindAttributes. (See foreach_server())
417c478bd9Sstevel@tonic-gate  *   4. Aggregate the servers' attributes into a config object. There
427c478bd9Sstevel@tonic-gate  *      is one config object associated with each context found in
437c478bd9Sstevel@tonic-gate  *      step 1. (See aggregate_attrs())
447c478bd9Sstevel@tonic-gate  *   5. Update the global config cache for each found context and its
457c478bd9Sstevel@tonic-gate  *      associated servers and attributes. (See update_config())
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * The entry point for ldap_cachemgr is discover(). The actual entry
487c478bd9Sstevel@tonic-gate  * point into the discovery routine is find_all_contexts(); the
497c478bd9Sstevel@tonic-gate  * code thereafter is actually not specific to LDAP, and could also
50*36e852a1SRaja Andra  * be used to discover YP, or any other server which conforms
517c478bd9Sstevel@tonic-gate  * to the SLP Naming and Directory abstract service type.
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  * find_all_attributes() takes as parameters three callback routines
547c478bd9Sstevel@tonic-gate  * which are used to report all information back to the caller. The
557c478bd9Sstevel@tonic-gate  * signatures and synopses of these routines are:
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * void *get_cfghandle(const char *domain);
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  *   Returns an opaque handle to a configuration object specific
607c478bd9Sstevel@tonic-gate  *   to the 'domain' parameter. 'domain' will be a naming context
617c478bd9Sstevel@tonic-gate  *   string, i.e. foo.bar.sun.com ( i.e. a secure-RPC domain-
627c478bd9Sstevel@tonic-gate  *   name).
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  * void aggregate(void *handle, const char *tag, const char *value);
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  *   Adds this tag / value pair to the set of aggregated attributes
677c478bd9Sstevel@tonic-gate  *   associated with the given handle.
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  * void set_cfghandle(void *handle);
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  *   Sets and destroys the config object; SLP will no longer attempt
727c478bd9Sstevel@tonic-gate  *   to use this handle after this call. Thus, this call marks the
737c478bd9Sstevel@tonic-gate  *   end of configuration information for this handle.
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #include <stdio.h>
777c478bd9Sstevel@tonic-gate #include <slp.h>
787c478bd9Sstevel@tonic-gate #include <stdlib.h>
797c478bd9Sstevel@tonic-gate #include <string.h>
807c478bd9Sstevel@tonic-gate #include <door.h>
817c478bd9Sstevel@tonic-gate #include <unistd.h>
827c478bd9Sstevel@tonic-gate #include "ns_sldap.h"
837c478bd9Sstevel@tonic-gate #include "ns_internal.h"
847c478bd9Sstevel@tonic-gate #include "cachemgr.h"
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #define	ABSTYPE		"service:naming-directory"
877c478bd9Sstevel@tonic-gate #define	CONTEXT_ATTR	"naming-context"
887c478bd9Sstevel@tonic-gate #define	LDAP_DOMAIN_ATTR "x-sun-rpcdomain"
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /* The configuration cookie passed along through all SLP callbacks. */
917c478bd9Sstevel@tonic-gate struct config_cookie {
927c478bd9Sstevel@tonic-gate 	SLPHandle	h;		/* An open SLPHandle */
937c478bd9Sstevel@tonic-gate 	const char	*type;		/* The full service type to use */
947c478bd9Sstevel@tonic-gate 	char		*scopes;	/* A list of scopes to use */
957c478bd9Sstevel@tonic-gate 	const char	*context_attr;	/* Which attr to use for the ctx */
967c478bd9Sstevel@tonic-gate 	void		*cache_cfg;	/* caller-supplied config object */
977c478bd9Sstevel@tonic-gate 	void *(*get_cfghandle)(const char *);
987c478bd9Sstevel@tonic-gate 	void (*aggregate)(void *, const char *, const char *);
997c478bd9Sstevel@tonic-gate 	void (*set_cfghandle)(void *);
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate extern admin_t current_admin;	/* ldap_cachemgr's admin struct */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate  * Utility routine: getlocale():
1067c478bd9Sstevel@tonic-gate  * Returns the locale specified by the SLP locale property, or just
1077c478bd9Sstevel@tonic-gate  * returns the default SLP locale if the property was not set.
1087c478bd9Sstevel@tonic-gate  */
getlocale()1097c478bd9Sstevel@tonic-gate static const char *getlocale() {
1107c478bd9Sstevel@tonic-gate 	const char *locale = SLPGetProperty("net.slp.locale");
1117c478bd9Sstevel@tonic-gate 	return (locale ? locale : "en");
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * Utility routine: next_attr():
1167c478bd9Sstevel@tonic-gate  * Parses an SLP attribute string. On the first call, *type
1177c478bd9Sstevel@tonic-gate  * must be set to 0, and *s_inout must point to the beginning
1187c478bd9Sstevel@tonic-gate  * of the attr string. The following results are possible:
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  *   If the term is of the form 'tag' only, *t_inout is set to tag,
1217c478bd9Sstevel@tonic-gate  *     and *v_inout is set to NULL.
1227c478bd9Sstevel@tonic-gate  *   If the term is of the form '(tag=val)', *t_inout and *v_inout
1237c478bd9Sstevel@tonic-gate  *     are set to the tag and val strings, respectively.
1247c478bd9Sstevel@tonic-gate  *   If the term is of the form '(tag=val1,val2,..,valN)', on each
1257c478bd9Sstevel@tonic-gate  *     successive call, next_attr will return the next value. On the
1267c478bd9Sstevel@tonic-gate  *     first invocation, tag is set to 'tag'; on successive invocations,
1277c478bd9Sstevel@tonic-gate  *     tag is set to *t_inout.
1287c478bd9Sstevel@tonic-gate  *
1297c478bd9Sstevel@tonic-gate  * The string passed in *s_inout is destructively modified; all values
1307c478bd9Sstevel@tonic-gate  * returned simply point into the initial string. Hence the caller
1317c478bd9Sstevel@tonic-gate  * is responsible for all memory management. The type parameter is
1327c478bd9Sstevel@tonic-gate  * for internal use only and should be set to 0 by the caller only
1337c478bd9Sstevel@tonic-gate  * on the first invocation.
1347c478bd9Sstevel@tonic-gate  *
1357c478bd9Sstevel@tonic-gate  * If more attrs are available, returns SLP_TRUE, otherwise returns
1367c478bd9Sstevel@tonic-gate  * SLP_FALSE. If SLP_FALSE is returned, all value-result parameters
1377c478bd9Sstevel@tonic-gate  * will be undefined, and should not be used.
1387c478bd9Sstevel@tonic-gate  */
next_attr(char ** t_inout,char ** v_inout,char ** s_inout,int * type)1397c478bd9Sstevel@tonic-gate static SLPBoolean next_attr(char **t_inout, char **v_inout,
1407c478bd9Sstevel@tonic-gate 			    char **s_inout, int *type) {
1417c478bd9Sstevel@tonic-gate 	char *end = NULL;
1427c478bd9Sstevel@tonic-gate 	char *tag = NULL;
1437c478bd9Sstevel@tonic-gate 	char *val = NULL;
1447c478bd9Sstevel@tonic-gate 	char *state = NULL;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (!t_inout || !v_inout)
1477c478bd9Sstevel@tonic-gate 	    return (SLP_FALSE);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	if (!s_inout || !*s_inout || !**s_inout)
1507c478bd9Sstevel@tonic-gate 	    return (SLP_FALSE);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	state = *s_inout;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* type: 0 = start, 1 = '(tag=val)' type, 2 = 'tag' type */
1557c478bd9Sstevel@tonic-gate 	switch (*type) {
1567c478bd9Sstevel@tonic-gate 	case 0:
1577c478bd9Sstevel@tonic-gate 	    switch (*state) {
1587c478bd9Sstevel@tonic-gate 	    case '(':
1597c478bd9Sstevel@tonic-gate 		*type = 1;
1607c478bd9Sstevel@tonic-gate 		break;
1617c478bd9Sstevel@tonic-gate 	    case ',':
1627c478bd9Sstevel@tonic-gate 		state++;
1637c478bd9Sstevel@tonic-gate 		*type = 0;
1647c478bd9Sstevel@tonic-gate 		break;
1657c478bd9Sstevel@tonic-gate 	    default:
1667c478bd9Sstevel@tonic-gate 		*type = 2;
1677c478bd9Sstevel@tonic-gate 	    }
1687c478bd9Sstevel@tonic-gate 	    *s_inout = state;
1697c478bd9Sstevel@tonic-gate 	    return (next_attr(t_inout, v_inout, s_inout, type));
1707c478bd9Sstevel@tonic-gate 	    break;
1717c478bd9Sstevel@tonic-gate 	case 1:
1727c478bd9Sstevel@tonic-gate 	    switch (*state) {
1737c478bd9Sstevel@tonic-gate 	    case '(':
1747c478bd9Sstevel@tonic-gate 		/* start of attr of the form (tag=val[,val]) */
1757c478bd9Sstevel@tonic-gate 		state++;
1767c478bd9Sstevel@tonic-gate 		tag = state;
1777c478bd9Sstevel@tonic-gate 		end = strchr(state, ')');	/* for sanity checking */
1787c478bd9Sstevel@tonic-gate 		if (!end)
1797c478bd9Sstevel@tonic-gate 		    return (SLP_FALSE);	/* fatal parse error */
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 		state = strchr(tag, '=');
1827c478bd9Sstevel@tonic-gate 		if (state) {
1837c478bd9Sstevel@tonic-gate 		    if (state > end)
1847c478bd9Sstevel@tonic-gate 			return (SLP_FALSE);  /* fatal parse err */
1857c478bd9Sstevel@tonic-gate 		    *state++ = 0;
1867c478bd9Sstevel@tonic-gate 		} else {
1877c478bd9Sstevel@tonic-gate 		    return (SLP_FALSE);	/* fatal parse error */
1887c478bd9Sstevel@tonic-gate 		}
1897c478bd9Sstevel@tonic-gate 		/* fallthru to default case, which handles multivals */
1907c478bd9Sstevel@tonic-gate 	    default:
1917c478bd9Sstevel@tonic-gate 		/* somewhere in a multivalued attr */
1927c478bd9Sstevel@tonic-gate 		if (!end) {	/* did not fallthru from '(' case */
1937c478bd9Sstevel@tonic-gate 		    tag = *t_inout;	/* leave tag as it was */
1947c478bd9Sstevel@tonic-gate 		    end = strchr(state, ')');
1957c478bd9Sstevel@tonic-gate 		    if (!end)
1967c478bd9Sstevel@tonic-gate 			return (SLP_FALSE);	/* fatal parse error */
1977c478bd9Sstevel@tonic-gate 		}
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 		val = state;
2007c478bd9Sstevel@tonic-gate 		state = strchr(val, ',');	/* is this attr multivalued? */
2017c478bd9Sstevel@tonic-gate 		if (!state || state > end) {
2027c478bd9Sstevel@tonic-gate 		    /* no, so skip to the next attr */
2037c478bd9Sstevel@tonic-gate 		    state = end;
2047c478bd9Sstevel@tonic-gate 		    *type = 0;
2057c478bd9Sstevel@tonic-gate 		}	/* else attr is multivalued */
2067c478bd9Sstevel@tonic-gate 		*state++ = 0;
2077c478bd9Sstevel@tonic-gate 		break;
2087c478bd9Sstevel@tonic-gate 	    }
2097c478bd9Sstevel@tonic-gate 	    break;
2107c478bd9Sstevel@tonic-gate 	case 2:
2117c478bd9Sstevel@tonic-gate 	    /* attr term with tag only */
2127c478bd9Sstevel@tonic-gate 	    tag = state;
2137c478bd9Sstevel@tonic-gate 	    state = strchr(tag, ',');
2147c478bd9Sstevel@tonic-gate 	    if (state) {
2157c478bd9Sstevel@tonic-gate 		*state++ = 0;
2167c478bd9Sstevel@tonic-gate 	    }
2177c478bd9Sstevel@tonic-gate 	    val = NULL;
2187c478bd9Sstevel@tonic-gate 	    *type = 0;
2197c478bd9Sstevel@tonic-gate 	    break;
2207c478bd9Sstevel@tonic-gate 	default:
2217c478bd9Sstevel@tonic-gate 	    return (SLP_FALSE);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	*t_inout = tag;
2257c478bd9Sstevel@tonic-gate 	*v_inout = val;
2267c478bd9Sstevel@tonic-gate 	*s_inout = state;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate  * The SLP callback routine for foreach_server(). Aggregates each
2337c478bd9Sstevel@tonic-gate  * server's attributes into the caller-specified config object.
2347c478bd9Sstevel@tonic-gate  */
2357c478bd9Sstevel@tonic-gate /*ARGSUSED*/
aggregate_attrs(SLPHandle h,const char * attrs_in,SLPError errin,void * cookie)2367c478bd9Sstevel@tonic-gate static SLPBoolean aggregate_attrs(SLPHandle h, const char *attrs_in,
2377c478bd9Sstevel@tonic-gate 				    SLPError errin, void *cookie) {
2387c478bd9Sstevel@tonic-gate 	char *tag, *val, *state;
2397c478bd9Sstevel@tonic-gate 	char *unesc_tag, *unesc_val;
2407c478bd9Sstevel@tonic-gate 	int type = 0;
2417c478bd9Sstevel@tonic-gate 	char *attrs;
2427c478bd9Sstevel@tonic-gate 	SLPError err;
2437c478bd9Sstevel@tonic-gate 	struct config_cookie *cfg = (struct config_cookie *)cookie;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (errin != SLP_OK) {
2467c478bd9Sstevel@tonic-gate 	    return (SLP_TRUE);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	attrs = strdup(attrs_in);
2507c478bd9Sstevel@tonic-gate 	state = attrs;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	while (next_attr(&tag, &val, &state, &type)) {
2537c478bd9Sstevel@tonic-gate 	    unesc_tag = unesc_val = NULL;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	    if (tag) {
2567c478bd9Sstevel@tonic-gate 		if ((err = SLPUnescape(tag, &unesc_tag, SLP_TRUE)) != SLP_OK) {
2577c478bd9Sstevel@tonic-gate 		    unesc_tag = NULL;
2587c478bd9Sstevel@tonic-gate 		    if (current_admin.debug_level >= DBG_ALL) {
2597c478bd9Sstevel@tonic-gate 			(void) logit("aggregate_attrs: ",
2607c478bd9Sstevel@tonic-gate 				"could not unescape attr tag %s:%s\n",
2617c478bd9Sstevel@tonic-gate 				tag, slp_strerror(err));
2627c478bd9Sstevel@tonic-gate 		    }
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 	    }
2657c478bd9Sstevel@tonic-gate 	    if (val) {
2667c478bd9Sstevel@tonic-gate 		if ((err = SLPUnescape(val, &unesc_val, SLP_FALSE))
2677c478bd9Sstevel@tonic-gate 		    != SLP_OK) {
2687c478bd9Sstevel@tonic-gate 		    unesc_val = NULL;
2697c478bd9Sstevel@tonic-gate 		    if (current_admin.debug_level >= DBG_ALL) {
2707c478bd9Sstevel@tonic-gate 			(void) logit("aggregate_attrs: ",
2717c478bd9Sstevel@tonic-gate 				"could not unescape attr val %s:%s\n",
2727c478bd9Sstevel@tonic-gate 				val, slp_strerror(err));
2737c478bd9Sstevel@tonic-gate 		    }
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 	    }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_ALL) {
2787c478bd9Sstevel@tonic-gate 		(void) logit("discovery:\t\t%s=%s\n",
2797c478bd9Sstevel@tonic-gate 			(unesc_tag ? unesc_tag : "NULL"),
2807c478bd9Sstevel@tonic-gate 			(unesc_val ? unesc_val : "NULL"));
2817c478bd9Sstevel@tonic-gate 	    }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	    cfg->aggregate(cfg->cache_cfg, unesc_tag, unesc_val);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	    if (unesc_tag) free(unesc_tag);
2867c478bd9Sstevel@tonic-gate 	    if (unesc_val) free(unesc_val);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	if (attrs) free(attrs);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate  * The SLP callback routine for update_config(). For each
2967c478bd9Sstevel@tonic-gate  * server found, retrieves that server's attributes.
2977c478bd9Sstevel@tonic-gate  */
2987c478bd9Sstevel@tonic-gate /*ARGSUSED*/
foreach_server(SLPHandle hin,const char * u,unsigned short life,SLPError errin,void * cookie)2997c478bd9Sstevel@tonic-gate static SLPBoolean foreach_server(SLPHandle hin, const char *u,
3007c478bd9Sstevel@tonic-gate 				unsigned short life,
3017c478bd9Sstevel@tonic-gate 				SLPError errin, void *cookie) {
3027c478bd9Sstevel@tonic-gate 	SLPError err;
3037c478bd9Sstevel@tonic-gate 	struct config_cookie *cfg = (struct config_cookie *)cookie;
3047c478bd9Sstevel@tonic-gate 	SLPHandle h = cfg->h;	/* an open handle */
3057c478bd9Sstevel@tonic-gate 	SLPSrvURL *surl = NULL;
3067c478bd9Sstevel@tonic-gate 	char *url = NULL;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (errin != SLP_OK) {
3097c478bd9Sstevel@tonic-gate 	    return (SLP_TRUE);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/* dup url so we can slice 'n dice */
3137c478bd9Sstevel@tonic-gate 	if (!(url = strdup(u))) {
3147c478bd9Sstevel@tonic-gate 	    (void) logit("foreach_server: no memory");
3157c478bd9Sstevel@tonic-gate 	    return (SLP_FALSE);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	if ((err = SLPParseSrvURL(url, &surl)) != SLP_OK) {
3197c478bd9Sstevel@tonic-gate 	    free(url);
3207c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_NETLOOKUPS) {
3217c478bd9Sstevel@tonic-gate 		(void) logit("foreach_server: ",
3227c478bd9Sstevel@tonic-gate 				"dropping unparsable URL %s: %s\n",
3237c478bd9Sstevel@tonic-gate 				url, slp_strerror(err));
3247c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);
3257c478bd9Sstevel@tonic-gate 	    }
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
3297c478bd9Sstevel@tonic-gate 	    (void) logit("discovery:\tserver: %s\n", surl->s_pcHost);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/* retrieve all attrs for this server */
3337c478bd9Sstevel@tonic-gate 	err = SLPFindAttrs(h, u, cfg->scopes, "", aggregate_attrs, cookie);
3347c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
3357c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_NETLOOKUPS) {
3367c478bd9Sstevel@tonic-gate 		(void) logit("foreach_server: FindAttrs failed: %s\n",
3377c478bd9Sstevel@tonic-gate 				slp_strerror(err));
3387c478bd9Sstevel@tonic-gate 	    }
3397c478bd9Sstevel@tonic-gate 	    goto cleanup;
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/* add this server and its attrs to the config object */
3437c478bd9Sstevel@tonic-gate 	cfg->aggregate(cfg->cache_cfg, "_,_xservers_,_", surl->s_pcHost);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate cleanup:
3467c478bd9Sstevel@tonic-gate 	if (url) free(url);
3477c478bd9Sstevel@tonic-gate 	if (surl) SLPFree(surl);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate  * This routine does the dirty work of finding all servers for a
3547c478bd9Sstevel@tonic-gate  * given domain and injecting this information into the caller's
3557c478bd9Sstevel@tonic-gate  * configuration namespace via callbacks.
3567c478bd9Sstevel@tonic-gate  */
update_config(const char * context,struct config_cookie * cookie)3577c478bd9Sstevel@tonic-gate static void update_config(const char *context, struct config_cookie *cookie) {
3587c478bd9Sstevel@tonic-gate 	SLPHandle h = NULL;
3597c478bd9Sstevel@tonic-gate 	SLPHandle persrv_h = NULL;
3607c478bd9Sstevel@tonic-gate 	SLPError err;
3617c478bd9Sstevel@tonic-gate 	char *search = NULL;
3627c478bd9Sstevel@tonic-gate 	char *unesc_domain = NULL;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/* Unescape the naming context string */
3657c478bd9Sstevel@tonic-gate 	if ((err = SLPUnescape(context, &unesc_domain, SLP_FALSE)) != SLP_OK) {
3667c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_ALL) {
3677c478bd9Sstevel@tonic-gate 		(void) logit("update_config: ",
3687c478bd9Sstevel@tonic-gate 				"dropping unparsable domain: %s: %s\n",
3697c478bd9Sstevel@tonic-gate 				context, slp_strerror(err));
3707c478bd9Sstevel@tonic-gate 	    }
3717c478bd9Sstevel@tonic-gate 	    return;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	cookie->cache_cfg = cookie->get_cfghandle(unesc_domain);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	/* Open a handle which all attrs calls can use */
3777c478bd9Sstevel@tonic-gate 	if ((err = SLPOpen(getlocale(), SLP_FALSE, &persrv_h)) != SLP_OK) {
3787c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_NETLOOKUPS) {
3797c478bd9Sstevel@tonic-gate 		(void) logit("update_config: SLPOpen failed: %s\n",
3807c478bd9Sstevel@tonic-gate 				slp_strerror(err));
3817c478bd9Sstevel@tonic-gate 	    }
3827c478bd9Sstevel@tonic-gate 	    goto cleanup;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	cookie->h = persrv_h;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (current_admin.debug_level >= DBG_ALL) {
3887c478bd9Sstevel@tonic-gate 	    (void) logit("discovery: found naming context %s\n", context);
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/* (re)construct the search filter form the input context */
3927c478bd9Sstevel@tonic-gate 	search = malloc(strlen(cookie->context_attr) +
3937c478bd9Sstevel@tonic-gate 			strlen(context) +
3947c478bd9Sstevel@tonic-gate 			strlen("(=)") + 1);
3957c478bd9Sstevel@tonic-gate 	if (!search) {
3967c478bd9Sstevel@tonic-gate 	    (void) logit("update_config: no memory\n");
3977c478bd9Sstevel@tonic-gate 	    goto cleanup;
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 	(void) sprintf(search, "(%s=%s)", cookie->context_attr, context);
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/* Find all servers which serve this context */
4027c478bd9Sstevel@tonic-gate 	if ((err = SLPOpen(getlocale(), SLP_FALSE, &h)) != SLP_OK) {
4037c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_NETLOOKUPS) {
4047c478bd9Sstevel@tonic-gate 		(void) logit("upate_config: SLPOpen failed: %s\n",
4057c478bd9Sstevel@tonic-gate 				slp_strerror(err));
4067c478bd9Sstevel@tonic-gate 	    }
4077c478bd9Sstevel@tonic-gate 	    goto cleanup;
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	err = SLPFindSrvs(h, cookie->type, cookie->scopes,
4117c478bd9Sstevel@tonic-gate 				search, foreach_server, cookie);
4127c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
4137c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_NETLOOKUPS) {
4147c478bd9Sstevel@tonic-gate 		(void) logit("update_config: SLPFindSrvs failed: %s\n",
4157c478bd9Sstevel@tonic-gate 				slp_strerror(err));
4167c478bd9Sstevel@tonic-gate 	    }
4177c478bd9Sstevel@tonic-gate 	    goto cleanup;
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	/* update the config cache with the new info */
4217c478bd9Sstevel@tonic-gate 	cookie->set_cfghandle(cookie->cache_cfg);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate cleanup:
4247c478bd9Sstevel@tonic-gate 	if (h) SLPClose(h);
4257c478bd9Sstevel@tonic-gate 	if (persrv_h) SLPClose(persrv_h);
4267c478bd9Sstevel@tonic-gate 	if (search) free(search);
4277c478bd9Sstevel@tonic-gate 	if (unesc_domain) free(unesc_domain);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate /*
4317c478bd9Sstevel@tonic-gate  * The SLP callback routine for find_all_contexts(). For each context
4327c478bd9Sstevel@tonic-gate  * found, finds all the servers and their attributes.
4337c478bd9Sstevel@tonic-gate  */
4347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
foreach_context(SLPHandle h,const char * attrs_in,SLPError err,void * cookie)4357c478bd9Sstevel@tonic-gate static SLPBoolean foreach_context(SLPHandle h, const char *attrs_in,
4367c478bd9Sstevel@tonic-gate 				    SLPError err, void *cookie) {
4377c478bd9Sstevel@tonic-gate 	char *attrs, *tag, *val, *state;
4387c478bd9Sstevel@tonic-gate 	int type = 0;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
4417c478bd9Sstevel@tonic-gate 	    return (SLP_TRUE);
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 * Parse out each context. Attrs will be of the following form:
4467c478bd9Sstevel@tonic-gate 	 *   (naming-context=dc\3deng\2c dc\3dsun\2c dc\3dcom)
4477c478bd9Sstevel@tonic-gate 	 * Note that ',' and '=' are reserved in SLP, so they are escaped.
4487c478bd9Sstevel@tonic-gate 	 */
4497c478bd9Sstevel@tonic-gate 	attrs = strdup(attrs_in);	/* so we can slice'n'dice */
4507c478bd9Sstevel@tonic-gate 	if (!attrs) {
4517c478bd9Sstevel@tonic-gate 	    (void) logit("foreach_context: no memory\n");
4527c478bd9Sstevel@tonic-gate 	    return (SLP_FALSE);
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 	state = attrs;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	while (next_attr(&tag, &val, &state, &type)) {
4577c478bd9Sstevel@tonic-gate 	    update_config(val, cookie);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	free(attrs);
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate /*
4667c478bd9Sstevel@tonic-gate  * Initiates server and attribute discovery for the concrete type
4677c478bd9Sstevel@tonic-gate  * 'type'. Currently the only useful type is "ldap", but perhaps
4687c478bd9Sstevel@tonic-gate  * "nis" and "nisplus" will also be useful in the future.
4697c478bd9Sstevel@tonic-gate  *
4707c478bd9Sstevel@tonic-gate  * get_cfghandle, aggregate, and set_cfghandle are callback routines
4717c478bd9Sstevel@tonic-gate  * used to pass any discovered configuration information back to the
4727c478bd9Sstevel@tonic-gate  * caller. See the introduction at the top of this file for more info.
4737c478bd9Sstevel@tonic-gate  */
find_all_contexts(const char * type,void * (* get_cfghandle)(const char *),void (* aggregate)(void *,const char *,const char *),void (* set_cfghandle)(void *))4747c478bd9Sstevel@tonic-gate static void find_all_contexts(const char *type,
4757c478bd9Sstevel@tonic-gate 				void *(*get_cfghandle)(const char *),
4767c478bd9Sstevel@tonic-gate 				void (*aggregate)(
4777c478bd9Sstevel@tonic-gate 					void *, const char *, const char *),
4787c478bd9Sstevel@tonic-gate 				void (*set_cfghandle)(void *)) {
4797c478bd9Sstevel@tonic-gate 	SLPHandle h = NULL;
4807c478bd9Sstevel@tonic-gate 	SLPError err;
4817c478bd9Sstevel@tonic-gate 	struct config_cookie cookie[1];
4827c478bd9Sstevel@tonic-gate 	char *fulltype = NULL;
4837c478bd9Sstevel@tonic-gate 	char *scope = (char *)SLPGetProperty("net.slp.useScopes");
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	if (!scope || !*scope) {
4867c478bd9Sstevel@tonic-gate 	    scope = "default";
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	/* construct the full type from the partial type parameter */
4907c478bd9Sstevel@tonic-gate 	fulltype = malloc(strlen(ABSTYPE) + strlen(type) + 2);
4917c478bd9Sstevel@tonic-gate 	if (!fulltype) {
4927c478bd9Sstevel@tonic-gate 	    (void) logit("find_all_contexts: no memory");
4937c478bd9Sstevel@tonic-gate 	    goto done;
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 	(void) sprintf(fulltype, "%s:%s", ABSTYPE, type);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	/* set up the cookie for this discovery operation */
4987c478bd9Sstevel@tonic-gate 	memset(cookie, 0, sizeof (*cookie));
4997c478bd9Sstevel@tonic-gate 	cookie->type = fulltype;
5007c478bd9Sstevel@tonic-gate 	cookie->scopes = scope;
5017c478bd9Sstevel@tonic-gate 	if (strcasecmp(type, "ldap") == 0) {
5027c478bd9Sstevel@tonic-gate 		/* Sun LDAP is special */
5037c478bd9Sstevel@tonic-gate 	    cookie->context_attr = LDAP_DOMAIN_ATTR;
5047c478bd9Sstevel@tonic-gate 	} else {
5057c478bd9Sstevel@tonic-gate 	    cookie->context_attr = CONTEXT_ATTR;
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 	cookie->get_cfghandle = get_cfghandle;
5087c478bd9Sstevel@tonic-gate 	cookie->aggregate = aggregate;
5097c478bd9Sstevel@tonic-gate 	cookie->set_cfghandle = set_cfghandle;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	if ((err = SLPOpen(getlocale(), SLP_FALSE, &h)) != SLP_OK) {
5127c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_CANT_FIND) {
5137c478bd9Sstevel@tonic-gate 		(void) logit("discover: %s",
5147c478bd9Sstevel@tonic-gate 			    "Aborting discovery: SLPOpen failed: %s\n",
5157c478bd9Sstevel@tonic-gate 			    slp_strerror(err));
5167c478bd9Sstevel@tonic-gate 	    }
5177c478bd9Sstevel@tonic-gate 	    goto done;
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	/* use find attrs to get a list of all available contexts */
5217c478bd9Sstevel@tonic-gate 	err = SLPFindAttrs(h, fulltype, scope, cookie->context_attr,
5227c478bd9Sstevel@tonic-gate 			    foreach_context, cookie);
5237c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
5247c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_CANT_FIND) {
5257c478bd9Sstevel@tonic-gate 		(void) logit(
5267c478bd9Sstevel@tonic-gate 		"discover: Aborting discovery: SLPFindAttrs failed: %s\n",
5277c478bd9Sstevel@tonic-gate 			slp_strerror(err));
5287c478bd9Sstevel@tonic-gate 	    }
5297c478bd9Sstevel@tonic-gate 	    goto done;
5307c478bd9Sstevel@tonic-gate 	}
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate done:
5337c478bd9Sstevel@tonic-gate 	if (h) SLPClose(h);
5347c478bd9Sstevel@tonic-gate 	if (fulltype) free(fulltype);
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate /*
5387c478bd9Sstevel@tonic-gate  * This is the ldap_cachemgr entry point into SLP dynamic discovery. The
5397c478bd9Sstevel@tonic-gate  * parameter 'r' should be a pointer to an unsigned int containing
5407c478bd9Sstevel@tonic-gate  * the requested interval at which the network should be queried.
5417c478bd9Sstevel@tonic-gate  */
discover(void * r)5427c478bd9Sstevel@tonic-gate void discover(void *r) {
5437c478bd9Sstevel@tonic-gate 	unsigned short reqrefresh = *((unsigned int *)r);
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	for (;;) {
5467c478bd9Sstevel@tonic-gate 	    find_all_contexts("ldap",
5477c478bd9Sstevel@tonic-gate 				__cache_get_cfghandle,
5487c478bd9Sstevel@tonic-gate 				__cache_aggregate_params,
5497c478bd9Sstevel@tonic-gate 				__cache_set_cfghandle);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	    if (current_admin.debug_level >= DBG_ALL) {
5527c478bd9Sstevel@tonic-gate 		(void) logit(
5537c478bd9Sstevel@tonic-gate 			"dynamic discovery: using refresh interval %d\n",
5547c478bd9Sstevel@tonic-gate 			reqrefresh);
5557c478bd9Sstevel@tonic-gate 	    }
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	    (void) sleep(reqrefresh);
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate #endif /* SLP */
562