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