xref: /illumos-gate/usr/src/lib/libslp/clib/SLPUtils.c (revision 48d1bcbb)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * Public utilities and convenience calls (from the API spec):
297c478bd9Sstevel@tonic-gate  *	SLPFindScopes (queries for all known scopes)
307c478bd9Sstevel@tonic-gate  *	SLPEscape / Unescape
317c478bd9Sstevel@tonic-gate  *	SLPFree
327c478bd9Sstevel@tonic-gate  *	SLPSet/GetProperty
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <syslog.h>
397c478bd9Sstevel@tonic-gate #include <netdb.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate #include <libintl.h>
427c478bd9Sstevel@tonic-gate #include <slp-internal.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate struct scopes_tree {
457c478bd9Sstevel@tonic-gate 	void *scopes;
467c478bd9Sstevel@tonic-gate 	int len;
477c478bd9Sstevel@tonic-gate };
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate typedef SLPBoolean SLPScopeCallback(SLPHandle, const char *, SLPError, void *);
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static SLPSrvURLCallback collate_scopes;
527c478bd9Sstevel@tonic-gate static void collect_scopes(void *, VISIT, int, void *);
537c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_scope(slp_handle_impl_t *, char *,
547c478bd9Sstevel@tonic-gate 					SLPScopeCallback, void *,
557c478bd9Sstevel@tonic-gate 					void **, int *);
567c478bd9Sstevel@tonic-gate static SLPError SAAdvert_for_scopes(SLPHandle, void **);
577c478bd9Sstevel@tonic-gate static SLPError slp_unescape(const char *, char **, SLPBoolean, const char);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * Finds scopes according the the user administrative model.
617c478bd9Sstevel@tonic-gate  */
SLPFindScopes(SLPHandle hSLP,char ** ppcScopes)627c478bd9Sstevel@tonic-gate SLPError SLPFindScopes(SLPHandle hSLP, char **ppcScopes) {
637c478bd9Sstevel@tonic-gate 	SLPError err;
647c478bd9Sstevel@tonic-gate 	char *reply, *unesc_reply;
657c478bd9Sstevel@tonic-gate 	void *stree = NULL;
667c478bd9Sstevel@tonic-gate 	void *collator = NULL;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	if (!hSLP || !ppcScopes) {
697c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	/* first try administratively configured scopes */
737c478bd9Sstevel@tonic-gate 	if ((err = slp_administrative_scopes(ppcScopes, SLP_FALSE))
747c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
757c478bd9Sstevel@tonic-gate 		return (err);
767c478bd9Sstevel@tonic-gate 	}
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	if (*ppcScopes) {
797c478bd9Sstevel@tonic-gate 	    /* got scopes */
807c478bd9Sstevel@tonic-gate 	    return (SLP_OK);
817c478bd9Sstevel@tonic-gate 	}
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	/* DAs from active and passive discovery */
847c478bd9Sstevel@tonic-gate 	if ((err = slp_find_das("", &reply)) != SLP_OK &&
857c478bd9Sstevel@tonic-gate 	    err != SLP_NETWORK_ERROR)
867c478bd9Sstevel@tonic-gate 		return (err);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	/* Unpack the reply */
897c478bd9Sstevel@tonic-gate 	if (reply) {
907c478bd9Sstevel@tonic-gate 		int numResults = 0;	/* placeholder; not actually used */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 		/* tag call as internal */
937c478bd9Sstevel@tonic-gate 		((slp_handle_impl_t *)hSLP)->internal_call = SLP_TRUE;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 		(void) slp_unpackSrvReply(
967c478bd9Sstevel@tonic-gate 			hSLP, reply, collate_scopes,
977c478bd9Sstevel@tonic-gate 			&stree, &collator, &numResults);
987c478bd9Sstevel@tonic-gate 		/* invoke last call */
997c478bd9Sstevel@tonic-gate 		(void) slp_unpackSrvReply(
1007c478bd9Sstevel@tonic-gate 			hSLP, NULL, collate_scopes,
1017c478bd9Sstevel@tonic-gate 			&stree, &collator, &numResults);
1027c478bd9Sstevel@tonic-gate 		free(reply);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 		/* revert internal call tag */
1057c478bd9Sstevel@tonic-gate 		((slp_handle_impl_t *)hSLP)->internal_call = SLP_FALSE;
1067c478bd9Sstevel@tonic-gate 	}
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/* Finally, if no results yet, try SA discovery */
1097c478bd9Sstevel@tonic-gate 	if (!stree) {
1107c478bd9Sstevel@tonic-gate 	    (void) SAAdvert_for_scopes(hSLP, &stree);
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (!stree) {
1147c478bd9Sstevel@tonic-gate 		/* found none, so just return "default" */
1157c478bd9Sstevel@tonic-gate 		if (!(*ppcScopes = strdup("default"))) {
1167c478bd9Sstevel@tonic-gate 			slp_err(LOG_CRIT, 0, "SLPFindScopes", "out of memory");
1177c478bd9Sstevel@tonic-gate 			return (SLP_MEMORY_ALLOC_FAILED);
1187c478bd9Sstevel@tonic-gate 		}
1197c478bd9Sstevel@tonic-gate 		return (SLP_OK);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/* we now have a btree, each leaf of which is a unique scope */
1237c478bd9Sstevel@tonic-gate 	slp_twalk(stree, collect_scopes, 0, (void *) ppcScopes);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	/* unescape scopes list */
1267c478bd9Sstevel@tonic-gate 	if ((err = slp_unescape(*ppcScopes, &unesc_reply, SLP_FALSE, '%'))
1277c478bd9Sstevel@tonic-gate 	    == SLP_OK) {
1287c478bd9Sstevel@tonic-gate 		free(*ppcScopes);
1297c478bd9Sstevel@tonic-gate 		*ppcScopes = unesc_reply;
1307c478bd9Sstevel@tonic-gate 	} else {
1317c478bd9Sstevel@tonic-gate 		free(unesc_reply);
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	return (err);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * Finds scopes according to the adminstrative scoping model. A
1397c478bd9Sstevel@tonic-gate  * comma-seperated list of scopes is returned in *ppcScopes; the
1407c478bd9Sstevel@tonic-gate  * caller must free *ppcScopes.
1417c478bd9Sstevel@tonic-gate  * If the return_default parameter is true, and no scopes are found,
1427c478bd9Sstevel@tonic-gate  * *ppcScopes will be set to 'default', otherwise, *ppcScopes will
1437c478bd9Sstevel@tonic-gate  * be NULL. This helps simplify internal memory management.
1447c478bd9Sstevel@tonic-gate  */
slp_administrative_scopes(char ** ppcScopes,SLPBoolean return_default)1457c478bd9Sstevel@tonic-gate SLPError slp_administrative_scopes(char **ppcScopes,
1467c478bd9Sstevel@tonic-gate 					SLPBoolean return_default) {
1477c478bd9Sstevel@tonic-gate 	const char *useScopes;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	*ppcScopes = NULL;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/* @@@ first try DHCP */
1527c478bd9Sstevel@tonic-gate 	/* next try the useScopes property */
1537c478bd9Sstevel@tonic-gate 	useScopes = SLPGetProperty(SLP_CONFIG_USESCOPES);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if (useScopes && *useScopes) {
1567c478bd9Sstevel@tonic-gate 		if (!(*ppcScopes = strdup(useScopes))) {
1577c478bd9Sstevel@tonic-gate 			slp_err(LOG_CRIT, 0, "SLPFindScopes", "out of memory");
1587c478bd9Sstevel@tonic-gate 			return (SLP_MEMORY_ALLOC_FAILED);
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 		return (SLP_OK);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	/* found none, so just return "default" */
1647c478bd9Sstevel@tonic-gate 	if (return_default && !(*ppcScopes = strdup("default"))) {
1657c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPFindScopes", "out of memory");
1667c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 	return (SLP_OK);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * This function operates on the same btree as the collate_scopes().
1737c478bd9Sstevel@tonic-gate  * The difference is that this one is called for each
1747c478bd9Sstevel@tonic-gate  * SAAdvert recieved.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate /* ARGSUSED */
saadvert_callback(SLPHandle hp,char * scopes,SLPError err,void ** stree)1777c478bd9Sstevel@tonic-gate static SLPBoolean saadvert_callback(SLPHandle hp, char *scopes,
1787c478bd9Sstevel@tonic-gate 					SLPError err, void **stree) {
1797c478bd9Sstevel@tonic-gate 	char *s, *tstate;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
1827c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	for (
1867c478bd9Sstevel@tonic-gate 		s = strtok_r((char *)scopes, ",", &tstate);
1877c478bd9Sstevel@tonic-gate 		s;
1887c478bd9Sstevel@tonic-gate 		s = strtok_r(NULL, ",", &tstate)) {
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 		char *ascope, **srch;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 		if (!(ascope = strdup(s))) {	/* no memory! */
1937c478bd9Sstevel@tonic-gate 			slp_err(LOG_CRIT, 0, "collate_scopes",
1947c478bd9Sstevel@tonic-gate 				"out of memory");
1957c478bd9Sstevel@tonic-gate 			return (SLP_TRUE);
1967c478bd9Sstevel@tonic-gate 		}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		srch = slp_tsearch(
1997c478bd9Sstevel@tonic-gate 			(void *) ascope, stree,
2007c478bd9Sstevel@tonic-gate 			(int (*)(const void *, const void *)) slp_strcasecmp);
2017c478bd9Sstevel@tonic-gate 		if (*srch != ascope)
2027c478bd9Sstevel@tonic-gate 			/* scope is already in there, so just free ascope */
2037c478bd9Sstevel@tonic-gate 			free(ascope);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  * Generates an SAAdvert solicitation, and returns any scopes found
2117c478bd9Sstevel@tonic-gate  * from all recieved SAAdverts in stree. stree must be a btree
2127c478bd9Sstevel@tonic-gate  * structure.
2137c478bd9Sstevel@tonic-gate  */
SAAdvert_for_scopes(SLPHandle hSLP,void ** stree)2147c478bd9Sstevel@tonic-gate static SLPError SAAdvert_for_scopes(SLPHandle hSLP, void **stree) {
2157c478bd9Sstevel@tonic-gate 	SLPError err;
2167c478bd9Sstevel@tonic-gate 	SLPBoolean sync_state;
2177c478bd9Sstevel@tonic-gate 	slp_handle_impl_t *hp = (slp_handle_impl_t *)hSLP;
2187c478bd9Sstevel@tonic-gate 	char *predicate;
2197c478bd9Sstevel@tonic-gate 	const char *type_hint;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/* get type hint, if set */
2227c478bd9Sstevel@tonic-gate 	if ((type_hint = SLPGetProperty(SLP_CONFIG_TYPEHINT)) != NULL &&
2237c478bd9Sstevel@tonic-gate 		*type_hint != 0) {
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 		size_t hintlen = strlen(type_hint);
2267c478bd9Sstevel@tonic-gate 		size_t predlen = strlen("(service-type=)");
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 		/* check bounds */
2297c478bd9Sstevel@tonic-gate 		if (hintlen > (SLP_MAX_STRINGLEN - predlen)) {
2307c478bd9Sstevel@tonic-gate 			return (SLP_PARAMETER_BAD);
2317c478bd9Sstevel@tonic-gate 		}
2327c478bd9Sstevel@tonic-gate 		if (!(predicate = malloc(hintlen + predlen + 1))) {
2337c478bd9Sstevel@tonic-gate 			slp_err(LOG_CRIT, 0, "SAAdvert_for_scopes",
2347c478bd9Sstevel@tonic-gate 				"out of memory");
2357c478bd9Sstevel@tonic-gate 			return (SLP_MEMORY_ALLOC_FAILED);
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 		(void) strcpy(predicate, "(service-type=");
2387c478bd9Sstevel@tonic-gate 		(void) strcat(predicate, type_hint);
2397c478bd9Sstevel@tonic-gate 		(void) strcat(predicate, ")");
2407c478bd9Sstevel@tonic-gate 	} else {
2417c478bd9Sstevel@tonic-gate 		predicate = "";
2427c478bd9Sstevel@tonic-gate 		type_hint = NULL;
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	/* No callback for SLPFindScopes, so force synchronous mode only */
2467c478bd9Sstevel@tonic-gate 	sync_state = hp->async;
2477c478bd9Sstevel@tonic-gate 	hp->async = SLP_FALSE;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	if ((err = slp_start_call(hp)) != SLP_OK)
2507c478bd9Sstevel@tonic-gate 		return (err);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	err = slp_packSrvRqst("service:service-agent", predicate, hp);
2537c478bd9Sstevel@tonic-gate 
254*48d1bcbbSToomas Soome 	if (err == SLP_OK) {
2557c478bd9Sstevel@tonic-gate 		err = slp_ua_common(hSLP, "",
256*48d1bcbbSToomas Soome 		    (SLPGenericAppCB *)(uintptr_t)saadvert_callback,
257*48d1bcbbSToomas Soome 		    stree,
258*48d1bcbbSToomas Soome 		    (SLPMsgReplyCB *)unpackSAAdvert_scope);
259*48d1bcbbSToomas Soome 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if (type_hint) {
2627c478bd9Sstevel@tonic-gate 		free(predicate);
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	if (err != SLP_OK)
2667c478bd9Sstevel@tonic-gate 		slp_end_call(hp);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* restore sync state */
2697c478bd9Sstevel@tonic-gate 	hp->async = sync_state;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	return (err);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate  * Unpack an SAAdvert and pass each set of scopes into cb.
2767c478bd9Sstevel@tonic-gate  */
2777c478bd9Sstevel@tonic-gate /* ARGSUSED */
unpackSAAdvert_scope(slp_handle_impl_t * hSLP,char * reply,SLPScopeCallback cb,void * cookie,void ** collator,int * numResults)2787c478bd9Sstevel@tonic-gate static SLPBoolean unpackSAAdvert_scope(slp_handle_impl_t *hSLP, char *reply,
2797c478bd9Sstevel@tonic-gate 					SLPScopeCallback cb, void *cookie,
2807c478bd9Sstevel@tonic-gate 					void **collator, int *numResults) {
2817c478bd9Sstevel@tonic-gate 	char *surl, *scopes, *attrs;
2827c478bd9Sstevel@tonic-gate 	SLPBoolean cont;
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	if (!reply) {
2857c478bd9Sstevel@tonic-gate 		cb(hSLP, NULL, SLP_LAST_CALL, cookie);
2867c478bd9Sstevel@tonic-gate 		return (SLP_FALSE);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/* tag call as internal; gets all scopes, regardless of maxResults */
2907c478bd9Sstevel@tonic-gate 	hSLP->internal_call = SLP_TRUE;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	if (slp_unpackSAAdvert(reply, &surl, &scopes, &attrs) != SLP_OK) {
2937c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	cont = cb(hSLP, scopes, SLP_OK, cookie);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	/* revert internal_call tag */
2997c478bd9Sstevel@tonic-gate 	hSLP->internal_call = SLP_FALSE;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	free(surl);
3027c478bd9Sstevel@tonic-gate 	free(scopes);
3037c478bd9Sstevel@tonic-gate 	free(attrs);
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	return (cont);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate  * Creates a service request for finding DAs or SAs (based on 'filter'),
3107c478bd9Sstevel@tonic-gate  * and sends it to slpd, returning the reply in 'reply'.
3117c478bd9Sstevel@tonic-gate  */
slp_find_das(const char * filter,char ** reply)3127c478bd9Sstevel@tonic-gate SLPError slp_find_das(const char *filter, char **reply) {
3137c478bd9Sstevel@tonic-gate 	SLPError err;
3147c478bd9Sstevel@tonic-gate 	char *msg, hostname[MAXHOSTNAMELEN];
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	/* Try the cache first */
3177c478bd9Sstevel@tonic-gate 	if (*reply = slp_find_das_cached(filter)) {
3187c478bd9Sstevel@tonic-gate 		return (SLP_OK);
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	/*
3227c478bd9Sstevel@tonic-gate 	 * create a find scopes message:
3237c478bd9Sstevel@tonic-gate 	 * this is a SrvRqst for the type directory-agent.sun.
3247c478bd9Sstevel@tonic-gate 	 */
3257c478bd9Sstevel@tonic-gate 	/* use the local host's name for the scope */
3267c478bd9Sstevel@tonic-gate 	(void) gethostname(hostname, MAXHOSTNAMELEN);
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	err = slp_packSrvRqst_single(
3297c478bd9Sstevel@tonic-gate 		SLP_SUN_DA_TYPE, hostname, filter, &msg, "en");
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (err == SLP_OK) {
3327c478bd9Sstevel@tonic-gate 		err = slp_send2slpd(msg, reply);
3337c478bd9Sstevel@tonic-gate 		free(msg);
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	/* Add the reply to the cache */
3377c478bd9Sstevel@tonic-gate 	if (err == SLP_OK) {
3387c478bd9Sstevel@tonic-gate 		slp_put_das_cached(filter, *reply, slp_get_length(*reply));
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	return (err);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate /*
3457c478bd9Sstevel@tonic-gate  * This is called for each URL entry in the DA service reply (sun private).
3467c478bd9Sstevel@tonic-gate  * Contained within the cookie is a btree, to which it adds new
3477c478bd9Sstevel@tonic-gate  * scopes from the URL entry. The scopes are retrieved from the btree
3487c478bd9Sstevel@tonic-gate  * by traversing the tree in SLPFindScopes().
3497c478bd9Sstevel@tonic-gate  * SLPHandle h is NULL, so don't touch it!
3507c478bd9Sstevel@tonic-gate  */
3517c478bd9Sstevel@tonic-gate /*ARGSUSED*/
collate_scopes(SLPHandle h,const char * u,unsigned short lifetime,SLPError errCode,void * cookie)3527c478bd9Sstevel@tonic-gate static SLPBoolean collate_scopes(SLPHandle h, const char *u,
3537c478bd9Sstevel@tonic-gate 					unsigned short lifetime,
3547c478bd9Sstevel@tonic-gate 					SLPError errCode, void *cookie) {
3557c478bd9Sstevel@tonic-gate 	SLPSrvURL *surl;
3567c478bd9Sstevel@tonic-gate 	char *s, *tstate, *p, *url;
3577c478bd9Sstevel@tonic-gate 	void **collator = cookie;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	if (errCode != SLP_OK)
3607c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	/* dup url so as not to corrupt da cache */
3637c478bd9Sstevel@tonic-gate 	if (!(url = strdup(u))) {
3647c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "collate_scopes", "out of memory");
3657c478bd9Sstevel@tonic-gate 		return (SLP_FALSE);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	/* parse url into a SLPSrvURL struct */
3697c478bd9Sstevel@tonic-gate 	if (SLPParseSrvURL(url, &surl) != SLP_OK)
3707c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);	/* bad URL; skip it */
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	/* collate the scopes using the btree stree->scopes: */
3737c478bd9Sstevel@tonic-gate 	/* skip the 'scopes=' part */
3747c478bd9Sstevel@tonic-gate 	if (!(p = strchr(surl->s_pcSrvPart, '='))) {
3757c478bd9Sstevel@tonic-gate 		free(surl);
3767c478bd9Sstevel@tonic-gate 		return (SLP_TRUE);	/* bad URL; skip it */
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 	p++;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	for (
3817c478bd9Sstevel@tonic-gate 		s = strtok_r(p, ",", &tstate);
3827c478bd9Sstevel@tonic-gate 		s;
3837c478bd9Sstevel@tonic-gate 		s = strtok_r(NULL, ",", &tstate)) {
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 		char *ascope, **srch;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 		if (!(ascope = strdup(s))) {	/* no memory! */
3887c478bd9Sstevel@tonic-gate 			slp_err(LOG_CRIT, 0, "collate_scopes",
3897c478bd9Sstevel@tonic-gate 				"out of memory");
3907c478bd9Sstevel@tonic-gate 			free(surl);
3917c478bd9Sstevel@tonic-gate 			return (SLP_TRUE);
3927c478bd9Sstevel@tonic-gate 		}
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 		srch = slp_tsearch(
3957c478bd9Sstevel@tonic-gate 			(void *) ascope, collator,
3967c478bd9Sstevel@tonic-gate 			(int (*)(const void *, const void *)) slp_strcasecmp);
3977c478bd9Sstevel@tonic-gate 		if (*srch != ascope)
3987c478bd9Sstevel@tonic-gate 			/* scope is already in there, so just free ascope */
3997c478bd9Sstevel@tonic-gate 			free(ascope);
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	free(url);
4037c478bd9Sstevel@tonic-gate 	free(surl);
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	return (SLP_TRUE);
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate  * Each time we visit a node for the last time, copy that scope into
4107c478bd9Sstevel@tonic-gate  * the scope collection and free the scope string and the node.
4117c478bd9Sstevel@tonic-gate  */
4127c478bd9Sstevel@tonic-gate /*ARGSUSED*/
collect_scopes(void * node,VISIT order,int level,void * cookie)4137c478bd9Sstevel@tonic-gate static void collect_scopes(void *node, VISIT order, int level, void *cookie) {
4147c478bd9Sstevel@tonic-gate 	char **scopes = (char **)cookie;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	if (order == endorder || order == leaf) {
4177c478bd9Sstevel@tonic-gate 		char *s = *(char **)node;
4187c478bd9Sstevel@tonic-gate 		slp_add2list(s, scopes, SLP_FALSE);
4197c478bd9Sstevel@tonic-gate 		free(s);
4207c478bd9Sstevel@tonic-gate 		free(node);
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
SLPFree(void * pvMem)4247c478bd9Sstevel@tonic-gate void SLPFree(void *pvMem) {
4257c478bd9Sstevel@tonic-gate 	if (pvMem)
4267c478bd9Sstevel@tonic-gate 		free(pvMem);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * Escape / Unescape
4317c478bd9Sstevel@tonic-gate  */
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate #define	isBadTagChar(c)	((c) == '*' || (c) == '_' || \
4347c478bd9Sstevel@tonic-gate 			(c) == '\n' || (c) == '\t' || (c) == '\r')
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate #define	isReserved(c)	((c) <= 31 || (c) == '(' || (c) == ')' || \
4377c478bd9Sstevel@tonic-gate 			(c) == ',' || (c) == '\\' || (c) == '!' || \
4387c478bd9Sstevel@tonic-gate 			(c) == '<' || (c) == '=' || (c) == '>' || \
4397c478bd9Sstevel@tonic-gate 			(c) == '~')
4407c478bd9Sstevel@tonic-gate 
SLPEscape(const char * pcInbuf,char ** ppcOutBuf,SLPBoolean isTag)4417c478bd9Sstevel@tonic-gate SLPError SLPEscape(const char *pcInbuf, char **ppcOutBuf, SLPBoolean isTag) {
4427c478bd9Sstevel@tonic-gate 	char *buf, *pin, *pout;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	if (!pcInbuf || !ppcOutBuf)
4457c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	if (!(buf = malloc(strlen(pcInbuf) * 3 + 1))) {
4487c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPEscape", "out of memory");
4497c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	*ppcOutBuf = buf;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	for (pin = (char *)pcInbuf, pout = buf; *pin; ) {
4547c478bd9Sstevel@tonic-gate 		int len;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		/* If char is start of multibyte char, just copy it in */
4577c478bd9Sstevel@tonic-gate 		if ((len = mblen(pin, MB_CUR_MAX)) > 1) {
4587c478bd9Sstevel@tonic-gate 			int i;
4597c478bd9Sstevel@tonic-gate 			for (i = 0; i < len && *pin; i++)
4607c478bd9Sstevel@tonic-gate 				*pout++ = *pin++;
4617c478bd9Sstevel@tonic-gate 			continue;
4627c478bd9Sstevel@tonic-gate 		}
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		/* check for bad tag */
4657c478bd9Sstevel@tonic-gate 		if (isTag && isBadTagChar(*pin))
4667c478bd9Sstevel@tonic-gate 			return (SLP_PARSE_ERROR);
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		if (isReserved(*pin)) {
4697c478bd9Sstevel@tonic-gate 			if (isTag)
4707c478bd9Sstevel@tonic-gate 				return (SLP_PARSE_ERROR);
4717c478bd9Sstevel@tonic-gate 			(void) sprintf(pout, "\\%.2x", *pin);
4727c478bd9Sstevel@tonic-gate 			pout += 3;
4737c478bd9Sstevel@tonic-gate 			pin++;
4747c478bd9Sstevel@tonic-gate 		} else {
4757c478bd9Sstevel@tonic-gate 			*pout++ = *pin++;
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 	*pout = 0;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	return (SLP_OK);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
SLPUnescape(const char * pcInbuf,char ** ppcOutBuf,SLPBoolean isTag)4837c478bd9Sstevel@tonic-gate SLPError SLPUnescape(const char *pcInbuf, char **ppcOutBuf, SLPBoolean isTag) {
4847c478bd9Sstevel@tonic-gate 	if (!pcInbuf || !ppcOutBuf)
4857c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	return (slp_unescape(pcInbuf, ppcOutBuf, isTag, '\\'));
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate  * The actual unescaping routine; allows for different escape chars.
4937c478bd9Sstevel@tonic-gate  */
slp_unescape(const char * pcInbuf,char ** ppcOutBuf,SLPBoolean isTag,const char esc_char)4947c478bd9Sstevel@tonic-gate static SLPError slp_unescape(const char *pcInbuf, char **ppcOutBuf,
4957c478bd9Sstevel@tonic-gate 				SLPBoolean isTag, const char esc_char) {
4967c478bd9Sstevel@tonic-gate 	char *buf, *pin, *pout, conv[3];
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (!(buf = malloc(strlen(pcInbuf) * 3 + 1))) {
4997c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPEscape", "out of memory");
5007c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 	*ppcOutBuf = buf;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	conv[2] = 0;
5057c478bd9Sstevel@tonic-gate 	for (pin = (char *)pcInbuf, pout = buf; *pin; ) {
5067c478bd9Sstevel@tonic-gate 		int len;
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		/* If char is start of multibyte char, just copy it in */
5097c478bd9Sstevel@tonic-gate 		if ((len = mblen(pin, MB_CUR_MAX)) > 1) {
5107c478bd9Sstevel@tonic-gate 			int i;
5117c478bd9Sstevel@tonic-gate 			for (i = 0; i < len && *pin; i++)
5127c478bd9Sstevel@tonic-gate 				*pout++ = *pin++;
5137c478bd9Sstevel@tonic-gate 			continue;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 		if (*pin == esc_char) {
5177c478bd9Sstevel@tonic-gate 			if (!pin[1] || !pin[2])
5187c478bd9Sstevel@tonic-gate 				return (SLP_PARSE_ERROR);
5197c478bd9Sstevel@tonic-gate 			pin++;
5207c478bd9Sstevel@tonic-gate 			conv[0] = *pin++;
5217c478bd9Sstevel@tonic-gate 			conv[1] = *pin++;
5227c478bd9Sstevel@tonic-gate 			*pout++ = (char)strtol(conv, NULL, 16);
5237c478bd9Sstevel@tonic-gate 			if (isTag && isBadTagChar(*pout))
5247c478bd9Sstevel@tonic-gate 				return (SLP_PARSE_ERROR);
5257c478bd9Sstevel@tonic-gate 		} else {
5267c478bd9Sstevel@tonic-gate 			*pout++ = *pin++;
5277c478bd9Sstevel@tonic-gate 		}
5287c478bd9Sstevel@tonic-gate 	}
5297c478bd9Sstevel@tonic-gate 	*pout = 0;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	return (SLP_OK);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate  * Properties
5367c478bd9Sstevel@tonic-gate  *
5377c478bd9Sstevel@tonic-gate  * All properties are stored in a global tree (prop_table). This
5387c478bd9Sstevel@tonic-gate  * tree is created and accessed by slp_tsearch and slp_tfind.
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate struct prop_entry {
5417c478bd9Sstevel@tonic-gate 	const char *key, *val;
5427c478bd9Sstevel@tonic-gate };
5437c478bd9Sstevel@tonic-gate typedef struct prop_entry slp_prop_entry_t;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /* Global properties table */
5467c478bd9Sstevel@tonic-gate static void *slp_props = NULL;
5477c478bd9Sstevel@tonic-gate static mutex_t prop_table_lock = DEFAULTMUTEX;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate static void setDefaults();
5507c478bd9Sstevel@tonic-gate 
compare_props(const void * a,const void * b)5517c478bd9Sstevel@tonic-gate static int compare_props(const void *a, const void *b) {
5527c478bd9Sstevel@tonic-gate 	return (strcmp(
5537c478bd9Sstevel@tonic-gate 		((slp_prop_entry_t *)a)->key,
5547c478bd9Sstevel@tonic-gate 		((slp_prop_entry_t *)b)->key));
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate 
SLPSetProperty(const char * pcName,const char * pcValue)5577c478bd9Sstevel@tonic-gate void SLPSetProperty(const char *pcName, const char *pcValue) {
5587c478bd9Sstevel@tonic-gate 	slp_prop_entry_t *pe, **pe2;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	if (!slp_props) setDefaults();
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	if (!pcName || !pcValue) {
5637c478bd9Sstevel@tonic-gate 		return;
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if (!(pe = malloc(sizeof (*pe)))) {
5677c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPSetProperty", "out of memory");
5687c478bd9Sstevel@tonic-gate 		return;
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/* place the strings under library ownership */
5727c478bd9Sstevel@tonic-gate 	if (!(pe->key = strdup(pcName))) {
5737c478bd9Sstevel@tonic-gate 		free(pe);
5747c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPSetProperty", "out of memory");
5757c478bd9Sstevel@tonic-gate 		return;
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	if (!(pe->val = strdup(pcValue))) {
5797c478bd9Sstevel@tonic-gate 		free((void *) pe->key);
5807c478bd9Sstevel@tonic-gate 		free(pe);
5817c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "SLPSetProperty", "out of memory");
5827c478bd9Sstevel@tonic-gate 		return;
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	/* is pcName already set? */
5867c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&prop_table_lock);
5877c478bd9Sstevel@tonic-gate 	pe2 = slp_tsearch((void *) pe, &slp_props, compare_props);
5887c478bd9Sstevel@tonic-gate 	if (pe != *pe2) {
5897c478bd9Sstevel@tonic-gate 		/* this prop is already set; overwrite the old value */
5907c478bd9Sstevel@tonic-gate 		free((void *) (*pe2)->val);
5917c478bd9Sstevel@tonic-gate 		(*pe2)->val = pe->val;
5927c478bd9Sstevel@tonic-gate 		free((void *) pe->key);
5937c478bd9Sstevel@tonic-gate 		free(pe);
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&prop_table_lock);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
SLPGetProperty(const char * pcName)5987c478bd9Sstevel@tonic-gate const char *SLPGetProperty(const char *pcName) {
5997c478bd9Sstevel@tonic-gate 	slp_prop_entry_t pe[1], **ans;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	if (!slp_props) setDefaults();
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (!pcName) {
6047c478bd9Sstevel@tonic-gate 		return (NULL);
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	pe->key = pcName;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&prop_table_lock);
6107c478bd9Sstevel@tonic-gate 	ans = slp_tfind(pe, &slp_props, compare_props);
6117c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&prop_table_lock);
6127c478bd9Sstevel@tonic-gate 	if (ans)
6137c478bd9Sstevel@tonic-gate 		return ((*ans)->val);
6147c478bd9Sstevel@tonic-gate 	return (NULL);
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate 
setDefaults()6177c478bd9Sstevel@tonic-gate static void setDefaults() {
6187c478bd9Sstevel@tonic-gate 	slp_prop_entry_t *pe;
6197c478bd9Sstevel@tonic-gate 	static mutex_t lock = DEFAULTMUTEX;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&lock);
6227c478bd9Sstevel@tonic-gate 	if (slp_props) {
6237c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&lock);
6247c478bd9Sstevel@tonic-gate 		return;
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6287c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_ISBROADCASTONLY);
6297c478bd9Sstevel@tonic-gate 	pe->val = strdup("false");
6307c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6337c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_MULTICASTTTL);
6347c478bd9Sstevel@tonic-gate 	pe->val = strdup("255");
6357c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6387c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_MULTICASTMAXWAIT);
6397c478bd9Sstevel@tonic-gate 	pe->val = strdup("15000");
6407c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6437c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_DATAGRAMTIMEOUTS);
6447c478bd9Sstevel@tonic-gate 	pe->val = strdup("2000,2000,2000");
6457c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6487c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_MULTICASTTIMEOUTS);
6497c478bd9Sstevel@tonic-gate 	pe->val = strdup("1000,3000,3000,3000,3000");
6507c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6537c478bd9Sstevel@tonic-gate 	pe->key = SLP_CONFIG_MTU; pe->val = "1400";
6547c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6577c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_MAXRESULTS);
6587c478bd9Sstevel@tonic-gate 	pe->val = strdup("-1");
6597c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6627c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_SECURITY_ON);
6637c478bd9Sstevel@tonic-gate 	pe->val = strdup("false");
6647c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	pe = malloc(sizeof (*pe));
6677c478bd9Sstevel@tonic-gate 	pe->key = strdup(SLP_CONFIG_BYPASS_AUTH);
6687c478bd9Sstevel@tonic-gate 	pe->val = strdup("false");
6697c478bd9Sstevel@tonic-gate 	(void) slp_tsearch((void *) pe, &slp_props, compare_props);
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	slp_readConfig();
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&lock);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate static const char *error_strings[] = {
6777c478bd9Sstevel@tonic-gate 	"OK",				/* 0 */
6787c478bd9Sstevel@tonic-gate 	"Language not supported",	/* -1 */
6797c478bd9Sstevel@tonic-gate 	"Parse error",			/* -2 */
6807c478bd9Sstevel@tonic-gate 	"Invalid registration",		/* -3 */
6817c478bd9Sstevel@tonic-gate 	"Scope not supported",		/* -4 */
6827c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -5 */
6837c478bd9Sstevel@tonic-gate 	"Authentication absent",	/* -6 */
6847c478bd9Sstevel@tonic-gate 	"Authentication failed",	/* -7 */
6857c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -8 */
6867c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -9 */
6877c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -10 */
6887c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -11 */
6897c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -12 */
6907c478bd9Sstevel@tonic-gate 	"Invalid update",		/* -13 */
6917c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -14 */
6927c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -15 */
6937c478bd9Sstevel@tonic-gate 	"Invalid error number",		/* -16 */
6947c478bd9Sstevel@tonic-gate 	"Not implemented",		/* -17 */
6957c478bd9Sstevel@tonic-gate 	"Buffer overflow",		/* -18 */
6967c478bd9Sstevel@tonic-gate 	"Network timed out",		/* -19 */
6977c478bd9Sstevel@tonic-gate 	"Network init failed",		/* -20 */
6987c478bd9Sstevel@tonic-gate 	"Memory alloc failed",		/* -21 */
6997c478bd9Sstevel@tonic-gate 	"Parameter bad",		/* -22 */
7007c478bd9Sstevel@tonic-gate 	"Network error",		/* -23 */
7017c478bd9Sstevel@tonic-gate 	"Internal system error",	/* -24 */
7027c478bd9Sstevel@tonic-gate 	"Handle in use",		/* -25 */
7037c478bd9Sstevel@tonic-gate 	"Type error"			/* -26 */
7047c478bd9Sstevel@tonic-gate };
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate #define	SLP_MAX_ERR_CNT	26
7077c478bd9Sstevel@tonic-gate 
slp_strerror(SLPError err)7087c478bd9Sstevel@tonic-gate const char *slp_strerror(SLPError err) {
7097c478bd9Sstevel@tonic-gate 	int abserr;
7107c478bd9Sstevel@tonic-gate 	const char *str;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	if (err == SLP_LAST_CALL) {
7137c478bd9Sstevel@tonic-gate 		str = "Last call";
7147c478bd9Sstevel@tonic-gate 	} else if (err == SLP_SECURITY_UNAVAILABLE) {
7157c478bd9Sstevel@tonic-gate 		str = "Security Implementation Unavailable";
7167c478bd9Sstevel@tonic-gate 	} else {
7177c478bd9Sstevel@tonic-gate 		abserr = abs(err);
7187c478bd9Sstevel@tonic-gate 		if (abserr > SLP_MAX_ERR_CNT) {
7197c478bd9Sstevel@tonic-gate 			str = "Invalid error number";
7207c478bd9Sstevel@tonic-gate 		} else {
7217c478bd9Sstevel@tonic-gate 			str = error_strings[abserr];
7227c478bd9Sstevel@tonic-gate 		}
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	return (dgettext("libslp", str));
7267c478bd9Sstevel@tonic-gate }
727