xref: /illumos-gate/usr/src/lib/libslp/clib/SLPReg.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  * This file contains all functions pertaining to registrations:
297c478bd9Sstevel@tonic-gate  *	SLPReg
307c478bd9Sstevel@tonic-gate  *	SLPDereg
317c478bd9Sstevel@tonic-gate  *	SLPDelAttrs
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Each function talks only to the local slpd, and receives a SrvAck
347c478bd9Sstevel@tonic-gate  * reply.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * These calls can operate in sync or async mode. Sync mode operates
377c478bd9Sstevel@tonic-gate  * as follows:
387c478bd9Sstevel@tonic-gate  *	format params into a char *msg
397c478bd9Sstevel@tonic-gate  *	send this msg to slpd
407c478bd9Sstevel@tonic-gate  *	invoke the SLPRegReport callback with the error code found in the
417c478bd9Sstevel@tonic-gate  *		reply from slpd
427c478bd9Sstevel@tonic-gate  *	return
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * Async mode operates as follows:
457c478bd9Sstevel@tonic-gate  *	format the params into a char *msg
467c478bd9Sstevel@tonic-gate  *	there is one thread per process which handles async regs
477c478bd9Sstevel@tonic-gate  *	make sure this thread is running
487c478bd9Sstevel@tonic-gate  *	the reg_thread monitors the global static reg_q for messages
497c478bd9Sstevel@tonic-gate  *	a queue message is represented as a struct reg_q_msg
507c478bd9Sstevel@tonic-gate  *	caller thread places the reg msg on the reg_q, and returns
517c478bd9Sstevel@tonic-gate  *	the reg_thread reads the message from the reg_q, and sends the
527c478bd9Sstevel@tonic-gate  *		msg to slpd
537c478bd9Sstevel@tonic-gate  *	the reg_thread then invokes the SLPRegReport callback with the error
547c478bd9Sstevel@tonic-gate  *		code found in the reply from slpd
557c478bd9Sstevel@tonic-gate  *	once started, the reg_thread manages registration refreshing.
567c478bd9Sstevel@tonic-gate  *		If there are no registrations to refresh, the thread exits.
577c478bd9Sstevel@tonic-gate  */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #include <stdio.h>
607c478bd9Sstevel@tonic-gate #include <stdlib.h>
617c478bd9Sstevel@tonic-gate #include <thread.h>
627c478bd9Sstevel@tonic-gate #include <synch.h>
637c478bd9Sstevel@tonic-gate #include <syslog.h>
647c478bd9Sstevel@tonic-gate #include <slp-internal.h>
657c478bd9Sstevel@tonic-gate #include <sys/time.h>
667c478bd9Sstevel@tonic-gate #include <time.h>
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* Indices into a reg_msg iovec for auth blocks */
697c478bd9Sstevel@tonic-gate #define	SLP_URL_AUTH	1
707c478bd9Sstevel@tonic-gate #define	SLP_ATTR_AUTH	3
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /* A registration / de-registration message */
737c478bd9Sstevel@tonic-gate struct reg_msg {
747c478bd9Sstevel@tonic-gate 	struct iovec *msgiov;	/* msg contents */
757c478bd9Sstevel@tonic-gate 	int msgiov_len;		/* number of iovec components in msgiov */
767c478bd9Sstevel@tonic-gate 	struct iovec urlbytes;
777c478bd9Sstevel@tonic-gate 	struct iovec attrbytes;
787c478bd9Sstevel@tonic-gate 	int urlauth;		/* index into authiov for URL auth blocks */
797c478bd9Sstevel@tonic-gate 	int attrauth;		/* index into authiov for attr auth blocks */
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * This is the message bundle passed to the reg thread via a queue.
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate struct reg_q_msg {
867c478bd9Sstevel@tonic-gate 	struct reg_msg *msg;
877c478bd9Sstevel@tonic-gate 	slp_handle_impl_t *hp;
887c478bd9Sstevel@tonic-gate 	SLPRegReport *cb;
897c478bd9Sstevel@tonic-gate 	void *cookie;
907c478bd9Sstevel@tonic-gate };
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * These structures and vars are used for automatic re-registering.
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate static struct rereg_entry {
967c478bd9Sstevel@tonic-gate 	char *url;
977c478bd9Sstevel@tonic-gate 	struct reg_msg *msg;
987c478bd9Sstevel@tonic-gate 	time_t wake_time;
997c478bd9Sstevel@tonic-gate 	unsigned short lifetime;
1007c478bd9Sstevel@tonic-gate 	struct rereg_entry *next;
1017c478bd9Sstevel@tonic-gate } *reregs;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate static time_t next_wake_time;
1047c478bd9Sstevel@tonic-gate static unsigned short granularity = 3600;
1057c478bd9Sstevel@tonic-gate static mutex_t rereg_lock = DEFAULTMUTEX;	/* protects the rereg struct */
1067c478bd9Sstevel@tonic-gate static mutex_t start_lock = DEFAULTMUTEX;	/* protects reg_thr creation */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate static slp_queue_t *reg_q;	/* the global registration queue */
1097c478bd9Sstevel@tonic-gate static int slp_reg_thr_running;	/* positive if reg_thread is running */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /* Private Utility Routines */
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static SLPBoolean check_reregs();
1147c478bd9Sstevel@tonic-gate static SLPError add_rereg(const char *, struct reg_msg *, unsigned short);
1157c478bd9Sstevel@tonic-gate static unsigned short dereg_rereg(const char *);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static SLPError enqueue_reg(slp_handle_impl_t *, struct reg_msg *,
1187c478bd9Sstevel@tonic-gate 			    void *, SLPRegReport *);
1197c478bd9Sstevel@tonic-gate static SLPError reg_impl(slp_handle_impl_t *, struct reg_msg *,
1207c478bd9Sstevel@tonic-gate 				void *, SLPRegReport *);
121*48d1bcbbSToomas Soome static void *reg_thread(void *);
1227c478bd9Sstevel@tonic-gate static SLPError start_reg_thr();
1237c478bd9Sstevel@tonic-gate static SLPError reg_common(slp_handle_impl_t *, struct reg_msg *,
1247c478bd9Sstevel@tonic-gate 				void *, SLPRegReport *);
1257c478bd9Sstevel@tonic-gate static SLPError UnpackSrvAck(char *, SLPError *);
1267c478bd9Sstevel@tonic-gate static SLPError packSrvReg(slp_handle_impl_t *, const char *,
1277c478bd9Sstevel@tonic-gate 				unsigned short, const char *, const char *,
1287c478bd9Sstevel@tonic-gate 				const char *, SLPBoolean, struct reg_msg **);
1297c478bd9Sstevel@tonic-gate static SLPError packSrvDereg(slp_handle_impl_t *, const char *,
1307c478bd9Sstevel@tonic-gate 				const char *, const char *, struct reg_msg **);
1317c478bd9Sstevel@tonic-gate static SLPError find_SAscopes(char **scopes);
1327c478bd9Sstevel@tonic-gate static void free_msgiov(struct iovec *, int);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /* Public API SA functionality */
1357c478bd9Sstevel@tonic-gate 
SLPReg(SLPHandle hSLP,const char * pcSrvURL,const unsigned short usLifetime,const char * pcSrvType,const char * pcAttrs,SLPBoolean fresh,SLPRegReport callback,void * pvUser)1367c478bd9Sstevel@tonic-gate SLPError SLPReg(SLPHandle   hSLP, const char  *pcSrvURL,
1377c478bd9Sstevel@tonic-gate 		const unsigned short usLifetime,
1387c478bd9Sstevel@tonic-gate 		const char  *pcSrvType,
1397c478bd9Sstevel@tonic-gate 		const char  *pcAttrs, SLPBoolean  fresh,
1407c478bd9Sstevel@tonic-gate 		SLPRegReport callback, void *pvUser) {
1417c478bd9Sstevel@tonic-gate 	SLPError err;
1427c478bd9Sstevel@tonic-gate 	char *pcScopeList;
1437c478bd9Sstevel@tonic-gate 	struct reg_msg *msg;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (!hSLP || !pcSrvURL || !*pcSrvURL || !pcSrvType ||
1467c478bd9Sstevel@tonic-gate 	    !pcAttrs || !callback) {
1477c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if ((strlen(pcSrvURL) > SLP_MAX_STRINGLEN) ||
1517c478bd9Sstevel@tonic-gate 	    (strlen(pcSrvType) > SLP_MAX_STRINGLEN) ||
1527c478bd9Sstevel@tonic-gate 	    (strlen(pcAttrs) > SLP_MAX_STRINGLEN)) {
1537c478bd9Sstevel@tonic-gate 	    return (SLP_PARAMETER_BAD);
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	if ((err = find_SAscopes(&pcScopeList)) != SLP_OK) {
1577c478bd9Sstevel@tonic-gate 		return (err);
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	if ((err = slp_start_call(hSLP)) != SLP_OK)
1617c478bd9Sstevel@tonic-gate 		return (err);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	/* format params into msg */
1647c478bd9Sstevel@tonic-gate 	if ((err = packSrvReg(
1657c478bd9Sstevel@tonic-gate 		hSLP, pcSrvURL, usLifetime, pcSrvType,
1667c478bd9Sstevel@tonic-gate 		pcScopeList, pcAttrs, fresh, &msg)) != SLP_OK) {
1677c478bd9Sstevel@tonic-gate 		free(pcScopeList);
1687c478bd9Sstevel@tonic-gate 		slp_end_call(hSLP);
1697c478bd9Sstevel@tonic-gate 		return (err);
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	if ((err = reg_common(hSLP, msg, pvUser, callback)) == SLP_OK &&
1737c478bd9Sstevel@tonic-gate 	    usLifetime == SLP_LIFETIME_MAXIMUM) {
1747c478bd9Sstevel@tonic-gate 		struct reg_msg *rereg_msg;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 		/* create a rereg message, with no attrs */
1777c478bd9Sstevel@tonic-gate 		err = packSrvReg(
1787c478bd9Sstevel@tonic-gate 			hSLP, pcSrvURL, usLifetime,
1797c478bd9Sstevel@tonic-gate 			pcSrvType, pcScopeList, "", SLP_TRUE, &rereg_msg);
1807c478bd9Sstevel@tonic-gate 		if (err == SLP_OK) {
1817c478bd9Sstevel@tonic-gate 			err = add_rereg(pcSrvURL, rereg_msg, usLifetime);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	free(pcScopeList);
1867c478bd9Sstevel@tonic-gate 	return (err);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
packSrvReg(slp_handle_impl_t * hp,const char * url,unsigned short lifetime,const char * type,const char * scope,const char * attrs,SLPBoolean fresh,struct reg_msg ** msg)1897c478bd9Sstevel@tonic-gate static SLPError packSrvReg(slp_handle_impl_t *hp, const char *url,
1907c478bd9Sstevel@tonic-gate 				unsigned short lifetime, const char *type,
1917c478bd9Sstevel@tonic-gate 				const char *scope, const char *attrs,
1927c478bd9Sstevel@tonic-gate 				SLPBoolean fresh, struct reg_msg **msg) {
1937c478bd9Sstevel@tonic-gate 	char *m = NULL;
1947c478bd9Sstevel@tonic-gate 	SLPError err;
1957c478bd9Sstevel@tonic-gate 	size_t msgLen, tmplen, len = 0;
1967c478bd9Sstevel@tonic-gate 	time_t ts;
1977c478bd9Sstevel@tonic-gate 	struct timeval tp[1];
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	/* calculate the timestamp */
2007c478bd9Sstevel@tonic-gate 	(void) gettimeofday(tp, NULL);
2017c478bd9Sstevel@tonic-gate 	ts = tp->tv_sec + lifetime;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* create the reg_msg */
2047c478bd9Sstevel@tonic-gate 	*msg = NULL;
2057c478bd9Sstevel@tonic-gate 	if (!(*msg = calloc(1, sizeof (**msg)))) {
2067c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvReg", "out of memory");
2077c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/* compute the total messge length */
2117c478bd9Sstevel@tonic-gate 	msgLen =
2127c478bd9Sstevel@tonic-gate 		slp_hdrlang_length(hp) +
2137c478bd9Sstevel@tonic-gate 		/* URL entry */
2147c478bd9Sstevel@tonic-gate 		5 + strlen(url) +
2157c478bd9Sstevel@tonic-gate 		/* srv reg msg */
2167c478bd9Sstevel@tonic-gate 		2 + strlen(type) +
2177c478bd9Sstevel@tonic-gate 		2 + strlen(scope) +
2187c478bd9Sstevel@tonic-gate 		2 + strlen(attrs);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/*
2217c478bd9Sstevel@tonic-gate 	 * Allocate memory for all the message except the auth blocks.
2227c478bd9Sstevel@tonic-gate 	 * The iovec msgiov actually contains only pointers into this
2237c478bd9Sstevel@tonic-gate 	 * memory.
2247c478bd9Sstevel@tonic-gate 	 */
2257c478bd9Sstevel@tonic-gate 	if (!(m = calloc(msgLen, 1))) {
2267c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvReg", "out of memory");
2277c478bd9Sstevel@tonic-gate 		err = SLP_MEMORY_ALLOC_FAILED;
2287c478bd9Sstevel@tonic-gate 		goto error;
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	/*
2327c478bd9Sstevel@tonic-gate 	 * Create iovec for the msg. The iovec components are layed out thus:
2337c478bd9Sstevel@tonic-gate 	 *   0: header + URL
2347c478bd9Sstevel@tonic-gate 	 *   1: URL auth block count, URL auth block
2357c478bd9Sstevel@tonic-gate 	 *   2: attrs
2367c478bd9Sstevel@tonic-gate 	 *   3: attrs auth block count, attr auth block
2377c478bd9Sstevel@tonic-gate 	 */
2387c478bd9Sstevel@tonic-gate 	if (!((*msg)->msgiov = calloc(4, sizeof (*((*msg)->msgiov))))) {
2397c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvReg", "out of memory");
2407c478bd9Sstevel@tonic-gate 		err = SLP_MEMORY_ALLOC_FAILED;
2417c478bd9Sstevel@tonic-gate 		goto error;
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 	(*msg)->msgiov_len = 4;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if ((err = slp_add_header(hp->locale, m, msgLen, SRVREG, 0, &len))
2467c478bd9Sstevel@tonic-gate 	    != SLP_OK)
2477c478bd9Sstevel@tonic-gate 		goto error;
2487c478bd9Sstevel@tonic-gate 	/* set fresh flag */
2497c478bd9Sstevel@tonic-gate 	if (fresh)
2507c478bd9Sstevel@tonic-gate 		slp_set_fresh(m);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* URL entry */
2537c478bd9Sstevel@tonic-gate 	len++;	/* skip reserved byte in URL entry */
2547c478bd9Sstevel@tonic-gate 	if ((err = slp_add_sht(m, msgLen, lifetime, &len)) != SLP_OK)
2557c478bd9Sstevel@tonic-gate 		goto error;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/* save pointer to URL for signing */
2587c478bd9Sstevel@tonic-gate 	tmplen = len;
2597c478bd9Sstevel@tonic-gate 	(*msg)->urlbytes.iov_base = m + len;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, url, &len)) != SLP_OK)
2627c478bd9Sstevel@tonic-gate 		goto error;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	(*msg)->urlbytes.iov_len = len - tmplen;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[0].iov_base = m;
2677c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[0].iov_len = len;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	/* add auth blocks for URL */
2707c478bd9Sstevel@tonic-gate 	err = slp_sign(&((*msg)->urlbytes), 1, ts,
2717c478bd9Sstevel@tonic-gate 			(*msg)->msgiov, SLP_URL_AUTH);
2727c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
2737c478bd9Sstevel@tonic-gate 		goto error;
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[2].iov_base = m + len;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	/* type, scopes, and attrs */
2797c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, type, &len)) != SLP_OK)
2807c478bd9Sstevel@tonic-gate 		goto error;
2817c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, scope, &len)) != SLP_OK)
2827c478bd9Sstevel@tonic-gate 		goto error;
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	/* save pointer to attr for signing */
2857c478bd9Sstevel@tonic-gate 	tmplen = len;
2867c478bd9Sstevel@tonic-gate 	(*msg)->attrbytes.iov_base = m + len;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, attrs, &len)) != SLP_OK)
2897c478bd9Sstevel@tonic-gate 		goto error;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	(*msg)->attrbytes.iov_len = len - tmplen;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	/* length of 2nd portion is len - length of 1st portion */
2947c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[2].iov_len = len - (*msg)->msgiov[0].iov_len;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	/* add auth blocks for attrs */
2977c478bd9Sstevel@tonic-gate 	err = slp_sign(&((*msg)->attrbytes), 1, ts,
2987c478bd9Sstevel@tonic-gate 			(*msg)->msgiov, SLP_ATTR_AUTH);
2997c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
3007c478bd9Sstevel@tonic-gate 		goto error;
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/* adjust msgLen with authblocks, and set header length */
3047c478bd9Sstevel@tonic-gate 	msgLen += (*msg)->msgiov[SLP_URL_AUTH].iov_len;
3057c478bd9Sstevel@tonic-gate 	msgLen += (*msg)->msgiov[SLP_ATTR_AUTH].iov_len;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	/* make sure msgLen is valid */
3087c478bd9Sstevel@tonic-gate 	if (msgLen > SLP_MAX_MSGLEN) {
3097c478bd9Sstevel@tonic-gate 		err = SLP_PARAMETER_BAD;
3107c478bd9Sstevel@tonic-gate 		goto error;
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate 	slp_set_length(m, msgLen);
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	return (SLP_OK);
3157c478bd9Sstevel@tonic-gate error:
3167c478bd9Sstevel@tonic-gate 	if (m) free(m);
3177c478bd9Sstevel@tonic-gate 	if (*msg) {
3187c478bd9Sstevel@tonic-gate 		if ((*msg)->msgiov) free_msgiov((*msg)->msgiov, 4);
3197c478bd9Sstevel@tonic-gate 		free(*msg);
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 	*msg = NULL;
3227c478bd9Sstevel@tonic-gate 	return (err);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate 
SLPDereg(SLPHandle hSLP,const char * pURL,SLPRegReport callback,void * pvUser)3257c478bd9Sstevel@tonic-gate SLPError SLPDereg(SLPHandle hSLP, const char *pURL,
3267c478bd9Sstevel@tonic-gate 			SLPRegReport callback, void *pvUser) {
3277c478bd9Sstevel@tonic-gate 	char *pcScopeList;
3287c478bd9Sstevel@tonic-gate 	struct reg_msg *msg;
3297c478bd9Sstevel@tonic-gate 	SLPError err;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (!hSLP || !pURL || !*pURL || !callback) {
3327c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	if (strlen(pURL) > SLP_MAX_STRINGLEN) {
3367c478bd9Sstevel@tonic-gate 	    return (SLP_PARAMETER_BAD);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	if ((err = find_SAscopes(&pcScopeList))
3407c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
3417c478bd9Sstevel@tonic-gate 		return (err);
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	if ((err = slp_start_call(hSLP)) != SLP_OK)
3457c478bd9Sstevel@tonic-gate 		return (err);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/* format params into msg */
3487c478bd9Sstevel@tonic-gate 	if ((err = packSrvDereg(hSLP, pURL, pcScopeList, NULL, &msg))
3497c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
3507c478bd9Sstevel@tonic-gate 		free(pcScopeList);
3517c478bd9Sstevel@tonic-gate 		slp_end_call(hSLP);
3527c478bd9Sstevel@tonic-gate 		return (err);
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	if ((err = reg_common(hSLP, msg, pvUser, callback)) == SLP_OK) {
3567c478bd9Sstevel@tonic-gate 		(void) dereg_rereg(pURL);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	free(pcScopeList);
3607c478bd9Sstevel@tonic-gate 	return (err);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
SLPDelAttrs(SLPHandle hSLP,const char * pURL,const char * pcAttrs,SLPRegReport callback,void * pvUser)3637c478bd9Sstevel@tonic-gate SLPError SLPDelAttrs(SLPHandle hSLP, const char *pURL,
3647c478bd9Sstevel@tonic-gate 			const char *pcAttrs,
3657c478bd9Sstevel@tonic-gate 			SLPRegReport callback, void *pvUser) {
3667c478bd9Sstevel@tonic-gate 	SLPError err;
3677c478bd9Sstevel@tonic-gate 	char *pcScopeList;
3687c478bd9Sstevel@tonic-gate 	struct reg_msg *msg;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	if (!hSLP || !pURL || !*pURL || !pcAttrs || !callback) {
3717c478bd9Sstevel@tonic-gate 		return (SLP_PARAMETER_BAD);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if ((strlen(pURL) > SLP_MAX_STRINGLEN) ||
3757c478bd9Sstevel@tonic-gate 	    (strlen(pcAttrs) > SLP_MAX_STRINGLEN)) {
3767c478bd9Sstevel@tonic-gate 	    return (SLP_PARAMETER_BAD);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if ((err = find_SAscopes(&pcScopeList))
3807c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
3817c478bd9Sstevel@tonic-gate 		return (err);
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	if ((err = slp_start_call(hSLP)) != SLP_OK)
3857c478bd9Sstevel@tonic-gate 		return (err);
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/* format params into msg */
3887c478bd9Sstevel@tonic-gate 	if ((err = packSrvDereg(hSLP, pURL, pcScopeList, pcAttrs, &msg))
3897c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
3907c478bd9Sstevel@tonic-gate 		free(pcScopeList);
3917c478bd9Sstevel@tonic-gate 		slp_end_call(hSLP);
3927c478bd9Sstevel@tonic-gate 		return (err);
3937c478bd9Sstevel@tonic-gate 	}
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	free(pcScopeList);
3967c478bd9Sstevel@tonic-gate 	return (reg_common(hSLP, msg, pvUser, callback));
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate 
packSrvDereg(slp_handle_impl_t * hp,const char * url,const char * scopes,const char * attrs,struct reg_msg ** msg)3997c478bd9Sstevel@tonic-gate static SLPError packSrvDereg(slp_handle_impl_t *hp, const char *url,
4007c478bd9Sstevel@tonic-gate 				const char *scopes, const char *attrs,
4017c478bd9Sstevel@tonic-gate 				struct reg_msg  **msg) {
4027c478bd9Sstevel@tonic-gate 	char *m = NULL;
4037c478bd9Sstevel@tonic-gate 	SLPError err;
4047c478bd9Sstevel@tonic-gate 	size_t msgLen, tmplen, len = 0;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	/* create the reg_msg */
4077c478bd9Sstevel@tonic-gate 	*msg = NULL;
4087c478bd9Sstevel@tonic-gate 	if (!(*msg = calloc(1, sizeof (**msg)))) {
4097c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvReg", "out of memory");
4107c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	/* compute the total message length */
4147c478bd9Sstevel@tonic-gate 	attrs = (attrs ? attrs : "");
4157c478bd9Sstevel@tonic-gate 	msgLen =
4167c478bd9Sstevel@tonic-gate 		slp_hdrlang_length(hp) +
4177c478bd9Sstevel@tonic-gate 		2 + strlen(scopes) +
4187c478bd9Sstevel@tonic-gate 		/* URL entry */
4197c478bd9Sstevel@tonic-gate 		5 + strlen(url) +
4207c478bd9Sstevel@tonic-gate 		2 + strlen(attrs);
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	if (!(m = calloc(msgLen, 1))) {
4237c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvDereg", "out of memory");
4247c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
4257c478bd9Sstevel@tonic-gate 	}
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	/*
4287c478bd9Sstevel@tonic-gate 	 * Create iovec for the msg. The iovec components are layed out thus:
4297c478bd9Sstevel@tonic-gate 	 *   0: header + URL
4307c478bd9Sstevel@tonic-gate 	 *   1: URL auth block count, URL auth block
4317c478bd9Sstevel@tonic-gate 	 *   2: attrs
4327c478bd9Sstevel@tonic-gate 	 */
4337c478bd9Sstevel@tonic-gate 	if (!((*msg)->msgiov = calloc(3, sizeof (*((*msg)->msgiov))))) {
4347c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "packSrvDereg", "out of memory");
4357c478bd9Sstevel@tonic-gate 		err = SLP_MEMORY_ALLOC_FAILED;
4367c478bd9Sstevel@tonic-gate 		goto error;
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	(*msg)->msgiov_len = 3;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if ((err = slp_add_header(
4417c478bd9Sstevel@tonic-gate 		hp->locale, m, msgLen, SRVDEREG, 0, &len)) != SLP_OK)
4427c478bd9Sstevel@tonic-gate 		goto error;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/* scopes */
4457c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, scopes, &len)) != SLP_OK)
4467c478bd9Sstevel@tonic-gate 		goto error;
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	/* URL Entry */
4497c478bd9Sstevel@tonic-gate 	len++;	/* skip reserved byte in URL entry */
4507c478bd9Sstevel@tonic-gate 	if ((err = slp_add_sht(m, msgLen, 0, &len)) != SLP_OK)
4517c478bd9Sstevel@tonic-gate 		goto error;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/* save pointer to URL for signing */
4547c478bd9Sstevel@tonic-gate 	tmplen = len;
4557c478bd9Sstevel@tonic-gate 	(*msg)->urlbytes.iov_base = m + len;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, url, &len)) != SLP_OK)
4587c478bd9Sstevel@tonic-gate 		goto error;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	(*msg)->urlbytes.iov_len = len - tmplen;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[0].iov_base = m;
4637c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[0].iov_len = len;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/* add auth blocks for URL */
4667c478bd9Sstevel@tonic-gate 	err = slp_sign(&((*msg)->urlbytes), 1, 0,
4677c478bd9Sstevel@tonic-gate 			(*msg)->msgiov, SLP_URL_AUTH);
4687c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
4697c478bd9Sstevel@tonic-gate 		goto error;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[2].iov_base = m + len;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	/* tag list */
4757c478bd9Sstevel@tonic-gate 	if ((err = slp_add_string(m, msgLen, attrs, &len)) != SLP_OK)
4767c478bd9Sstevel@tonic-gate 		goto error;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/* length of 2nd portion is len - length of 1st portion */
4797c478bd9Sstevel@tonic-gate 	(*msg)->msgiov[2].iov_len = len - (*msg)->msgiov[0].iov_len;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/* adjust msgLen with authblocks, and set header length */
4827c478bd9Sstevel@tonic-gate 	msgLen += (*msg)->msgiov[SLP_URL_AUTH].iov_len;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	/* make sure msgLen is valid */
4857c478bd9Sstevel@tonic-gate 	if (msgLen > SLP_MAX_MSGLEN) {
4867c478bd9Sstevel@tonic-gate 		err = SLP_PARAMETER_BAD;
4877c478bd9Sstevel@tonic-gate 		goto error;
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 	slp_set_length(m, msgLen);
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	return (SLP_OK);
4927c478bd9Sstevel@tonic-gate error:
4937c478bd9Sstevel@tonic-gate 	if (m) free(m);
4947c478bd9Sstevel@tonic-gate 	if (*msg) {
4957c478bd9Sstevel@tonic-gate 		if ((*msg)->msgiov) free_msgiov((*msg)->msgiov, 3);
4967c478bd9Sstevel@tonic-gate 		free(*msg);
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate 	*msg = NULL;
4997c478bd9Sstevel@tonic-gate 	return (err);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate  * Passes the packed message to the routines which talk to slpd.
5047c478bd9Sstevel@tonic-gate  */
reg_common(slp_handle_impl_t * hp,struct reg_msg * msg,void * cookie,SLPRegReport callback)5057c478bd9Sstevel@tonic-gate static SLPError reg_common(slp_handle_impl_t *hp, struct reg_msg *msg,
5067c478bd9Sstevel@tonic-gate 				void *cookie, SLPRegReport callback) {
5077c478bd9Sstevel@tonic-gate 	SLPError err;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if (!slp_reg_thr_running)
5107c478bd9Sstevel@tonic-gate 		if ((err = start_reg_thr()) != SLP_OK)
5117c478bd9Sstevel@tonic-gate 			goto reg_done;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if (hp->async)
5147c478bd9Sstevel@tonic-gate 		err = enqueue_reg(hp, msg, cookie, callback);
5157c478bd9Sstevel@tonic-gate 	else
5167c478bd9Sstevel@tonic-gate 		err = reg_impl(hp, msg, cookie, callback);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate reg_done:
5197c478bd9Sstevel@tonic-gate 	/* If an error occurred, end_call() will not have happened */
5207c478bd9Sstevel@tonic-gate 	if (err != SLP_OK)
5217c478bd9Sstevel@tonic-gate 		slp_end_call(hp);
5227c478bd9Sstevel@tonic-gate 	return (err);
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate /*
5267c478bd9Sstevel@tonic-gate  * Put a reg message on the queue. Assumes reg_thread is running.
5277c478bd9Sstevel@tonic-gate  */
enqueue_reg(slp_handle_impl_t * hp,struct reg_msg * msg,void * cookie,SLPRegReport cb)5287c478bd9Sstevel@tonic-gate static SLPError enqueue_reg(slp_handle_impl_t *hp, struct reg_msg *msg,
5297c478bd9Sstevel@tonic-gate 			    void *cookie, SLPRegReport cb) {
5307c478bd9Sstevel@tonic-gate 	struct reg_q_msg *rmsg;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	if (!(rmsg = malloc(sizeof (*rmsg)))) {
5337c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "enqueue_reg", "out of memory");
5347c478bd9Sstevel@tonic-gate 		return (SLP_MEMORY_ALLOC_FAILED);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	rmsg->msg = msg;
5387c478bd9Sstevel@tonic-gate 	rmsg->hp = hp;
5397c478bd9Sstevel@tonic-gate 	rmsg->cb = cb;
5407c478bd9Sstevel@tonic-gate 	rmsg->cookie = cookie;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	return (slp_enqueue(reg_q, rmsg));
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * Create a new reg_q and start the reg thread.
5477c478bd9Sstevel@tonic-gate  */
start_reg_thr()5487c478bd9Sstevel@tonic-gate static SLPError start_reg_thr() {
5497c478bd9Sstevel@tonic-gate 	SLPError err = SLP_OK;
5507c478bd9Sstevel@tonic-gate 	int terr;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&start_lock);
5537c478bd9Sstevel@tonic-gate 	/* make sure someone else hasn't already intialized the thread */
5547c478bd9Sstevel@tonic-gate 	if (slp_reg_thr_running) {
5557c478bd9Sstevel@tonic-gate 		goto start_done;
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	/* create the reg queue */
5597c478bd9Sstevel@tonic-gate 	reg_q = slp_new_queue(&err);
5607c478bd9Sstevel@tonic-gate 	if (err != SLP_OK) {
5617c478bd9Sstevel@tonic-gate 		goto start_done;
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	/* start the reg thread */
5657c478bd9Sstevel@tonic-gate 	if ((terr = thr_create(
566*48d1bcbbSToomas Soome 		0, 0, reg_thread,
5677c478bd9Sstevel@tonic-gate 		NULL, 0, NULL)) != 0) {
5687c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "start_reg_thr",
5697c478bd9Sstevel@tonic-gate 			"could not start thread: %s",
5707c478bd9Sstevel@tonic-gate 			strerror(terr));
5717c478bd9Sstevel@tonic-gate 		slp_destroy_queue(reg_q);
5727c478bd9Sstevel@tonic-gate 		err = SLP_INTERNAL_SYSTEM_ERROR;
5737c478bd9Sstevel@tonic-gate 		goto start_done;
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 	slp_reg_thr_running = 1;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate start_done:
5787c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&start_lock);
5797c478bd9Sstevel@tonic-gate 	return (err);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate  * This is what the permanent reg thread runs; it just sits in a loop
5847c478bd9Sstevel@tonic-gate  * monitoring the reg_q for new reg messages.
5857c478bd9Sstevel@tonic-gate  *
5867c478bd9Sstevel@tonic-gate  * To conserve resources,
5877c478bd9Sstevel@tonic-gate  * if there are no more registrations to refresh, it will exit.
5887c478bd9Sstevel@tonic-gate  */
589*48d1bcbbSToomas Soome static void *
reg_thread(void * arg __unused)590*48d1bcbbSToomas Soome reg_thread(void *arg __unused)
591*48d1bcbbSToomas Soome {
5927c478bd9Sstevel@tonic-gate 	timestruc_t timeout;
5937c478bd9Sstevel@tonic-gate 	timeout.tv_nsec = 0;
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	for (;;) {
5967c478bd9Sstevel@tonic-gate 		SLPBoolean etimed;
5977c478bd9Sstevel@tonic-gate 		struct reg_q_msg *rmsg;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 		/* get the next message from the queue */
6007c478bd9Sstevel@tonic-gate 		timeout.tv_sec =
601*48d1bcbbSToomas Soome 		    next_wake_time ? next_wake_time : time(NULL) + 5;
6027c478bd9Sstevel@tonic-gate 		rmsg = slp_dequeue_timed(reg_q, &timeout, &etimed);
6037c478bd9Sstevel@tonic-gate 		if (!rmsg && etimed == SLP_TRUE) {
6047c478bd9Sstevel@tonic-gate 			/* timed out */
6057c478bd9Sstevel@tonic-gate 			if (!check_reregs()) {
6067c478bd9Sstevel@tonic-gate 				/* no more reregs; shut down this thread */
6077c478bd9Sstevel@tonic-gate 				(void) mutex_lock(&start_lock);
6087c478bd9Sstevel@tonic-gate 				slp_destroy_queue(reg_q);
6097c478bd9Sstevel@tonic-gate 				slp_reg_thr_running = 0;
6107c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&start_lock);
6117c478bd9Sstevel@tonic-gate 				thr_exit(NULL);
6127c478bd9Sstevel@tonic-gate 			}
6137c478bd9Sstevel@tonic-gate 			continue;
6147c478bd9Sstevel@tonic-gate 		}
6157c478bd9Sstevel@tonic-gate 		if (!rmsg)
6167c478bd9Sstevel@tonic-gate 			continue;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		/* got a new message */
6197c478bd9Sstevel@tonic-gate 		(void) reg_impl(rmsg->hp, rmsg->msg, rmsg->cookie, rmsg->cb);
6207c478bd9Sstevel@tonic-gate 		free(rmsg);
6217c478bd9Sstevel@tonic-gate 		(void) check_reregs();
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate  * Unpacks a SrvAck.
6277c478bd9Sstevel@tonic-gate  * 'reply' should point to the beginning of the header.
6287c478bd9Sstevel@tonic-gate  */
UnpackSrvAck(char * reply,SLPError * ans)6297c478bd9Sstevel@tonic-gate static SLPError UnpackSrvAck(char *reply, SLPError *ans) {
6307c478bd9Sstevel@tonic-gate 	SLPError err;
6317c478bd9Sstevel@tonic-gate 	unsigned short langlen, call_err;
6327c478bd9Sstevel@tonic-gate 	char *p = reply + SLP_HDRLEN;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	langlen = slp_get_langlen(reply);
6357c478bd9Sstevel@tonic-gate 	p += langlen;
6367c478bd9Sstevel@tonic-gate 	if ((err = slp_get_sht(p, 0, NULL, &call_err)) != SLP_OK)
6377c478bd9Sstevel@tonic-gate 		return (err);
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	*ans = slp_map_err(call_err);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	return (SLP_OK);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate /*
6457c478bd9Sstevel@tonic-gate  * The dispatcher for SA messages. Sends a message to slpd, unpacks and
6467c478bd9Sstevel@tonic-gate  * dispatches the reply to the user callback.
6477c478bd9Sstevel@tonic-gate  */
reg_impl(slp_handle_impl_t * hp,struct reg_msg * msg,void * cookie,SLPRegReport cb)6487c478bd9Sstevel@tonic-gate static SLPError reg_impl(slp_handle_impl_t *hp, struct reg_msg *msg,
6497c478bd9Sstevel@tonic-gate 				void *cookie, SLPRegReport cb) {
6507c478bd9Sstevel@tonic-gate 	char *reply = NULL;
6517c478bd9Sstevel@tonic-gate 	SLPError err, call_err;
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	if (hp->cancel)
6547c478bd9Sstevel@tonic-gate 		goto transaction_complete;
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	if ((err = slp_send2slpd_iov(msg->msgiov, msg->msgiov_len, &reply))
6577c478bd9Sstevel@tonic-gate 	    != SLP_OK)
6587c478bd9Sstevel@tonic-gate 		goto transaction_complete;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	/* through with msg, so free it now */
6617c478bd9Sstevel@tonic-gate 	free_msgiov(msg->msgiov, msg->msgiov_len);
6627c478bd9Sstevel@tonic-gate 	free(msg);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	if ((err = UnpackSrvAck(reply, &call_err)) != SLP_OK)
6657c478bd9Sstevel@tonic-gate 		goto transaction_complete;
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	/* the reg thread doubles as the consumer thread for SA calls */
6687c478bd9Sstevel@tonic-gate 	hp->consumer_tid = thr_self();
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	cb(hp, call_err, cookie);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate transaction_complete:
6737c478bd9Sstevel@tonic-gate 	if (reply) {
6747c478bd9Sstevel@tonic-gate 		free(reply);
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 	slp_end_call(hp);
6777c478bd9Sstevel@tonic-gate 	return (err);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * Re-registration routines
6827c478bd9Sstevel@tonic-gate  */
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate  * Adds the registration contained in 'msg' to the refresh registration
6867c478bd9Sstevel@tonic-gate  * list managed by reg_thread.
6877c478bd9Sstevel@tonic-gate  * Only registrations which are meant to be permanent are refreshed,
6887c478bd9Sstevel@tonic-gate  * so we only allow reg's with lifetime == SLP_LIFETIME_PERMANENT into
6897c478bd9Sstevel@tonic-gate  * the rereg table.
6907c478bd9Sstevel@tonic-gate  */
add_rereg(const char * url,struct reg_msg * msg,unsigned short lifetime)6917c478bd9Sstevel@tonic-gate static SLPError add_rereg(const char *url, struct reg_msg *msg,
6927c478bd9Sstevel@tonic-gate 				unsigned short lifetime) {
6937c478bd9Sstevel@tonic-gate 	struct rereg_entry *reg;
6947c478bd9Sstevel@tonic-gate 	SLPError err = SLP_OK;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	if (lifetime != SLP_LIFETIME_MAXIMUM) {
6977c478bd9Sstevel@tonic-gate 		return (SLP_OK);
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&rereg_lock);
7017c478bd9Sstevel@tonic-gate 	/* alloc a new rereg entry */
7027c478bd9Sstevel@tonic-gate 	if (!(reg = malloc(sizeof (*reg)))) {
7037c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "add_rereg", "out of memory");
7047c478bd9Sstevel@tonic-gate 		err = SLP_MEMORY_ALLOC_FAILED;
7057c478bd9Sstevel@tonic-gate 		goto done;
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	if (!(reg->url = strdup(url))) {
7097c478bd9Sstevel@tonic-gate 		free(reg);
7107c478bd9Sstevel@tonic-gate 		slp_err(LOG_CRIT, 0, "add_rereg", "out of memory");
7117c478bd9Sstevel@tonic-gate 		err = SLP_MEMORY_ALLOC_FAILED;
7127c478bd9Sstevel@tonic-gate 		goto done;
7137c478bd9Sstevel@tonic-gate 	}
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	reg->msg = msg;
7167c478bd9Sstevel@tonic-gate 	reg->lifetime = lifetime;
7177c478bd9Sstevel@tonic-gate 	reg->wake_time = (time(NULL) + lifetime) - 60;
7187c478bd9Sstevel@tonic-gate 	reg->next = NULL;
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	/* adjust the next wake time if necessary */
7217c478bd9Sstevel@tonic-gate 	next_wake_time =
7227c478bd9Sstevel@tonic-gate 		reg->wake_time < next_wake_time ?
7237c478bd9Sstevel@tonic-gate 		reg->wake_time : next_wake_time;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	/* add the rereg to the list */
7267c478bd9Sstevel@tonic-gate 	if (!reregs) {
7277c478bd9Sstevel@tonic-gate 		/* first one */
7287c478bd9Sstevel@tonic-gate 		reregs = reg;
7297c478bd9Sstevel@tonic-gate 		goto done;
7307c478bd9Sstevel@tonic-gate 	}
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	/* else add it to the beginning of the list */
7337c478bd9Sstevel@tonic-gate 	reg->next = reregs;
7347c478bd9Sstevel@tonic-gate 	reregs = reg;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate done:
7377c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&rereg_lock);
7387c478bd9Sstevel@tonic-gate 	return (err);
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate  * Walks through the rereg list and re-registers any which will expire
7437c478bd9Sstevel@tonic-gate  * before the reg thread wakes up and checks again.
7447c478bd9Sstevel@tonic-gate  * Returns true if there are more reregs on the list, false if none.
7457c478bd9Sstevel@tonic-gate  */
check_reregs()7467c478bd9Sstevel@tonic-gate static SLPBoolean check_reregs() {
7477c478bd9Sstevel@tonic-gate 	struct rereg_entry *p;
7487c478bd9Sstevel@tonic-gate 	time_t now, shortest_wait;
7497c478bd9Sstevel@tonic-gate 	SLPBoolean more = SLP_TRUE;
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&rereg_lock);
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	if (!reregs) {
7547c478bd9Sstevel@tonic-gate 		more = SLP_FALSE;
7557c478bd9Sstevel@tonic-gate 		goto done;
7567c478bd9Sstevel@tonic-gate 	}
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	now = time(NULL);
7597c478bd9Sstevel@tonic-gate 	shortest_wait = now + reregs->lifetime;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	for (p = reregs; p; p = p->next) {
7627c478bd9Sstevel@tonic-gate 		if (now > (p->wake_time - granularity)) {
7637c478bd9Sstevel@tonic-gate 		    char *reply;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 		    /* rereg it, first recalculating signature */
7667c478bd9Sstevel@tonic-gate 		    (void) slp_sign(&(p->msg->urlbytes), 1, now + p->lifetime,
7677c478bd9Sstevel@tonic-gate 				    p->msg->msgiov, 1);
7687c478bd9Sstevel@tonic-gate 		    (void) slp_sign(&(p->msg->attrbytes), 1, now + p->lifetime,
7697c478bd9Sstevel@tonic-gate 				    p->msg->msgiov, 3);
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 		    (void) slp_send2slpd_iov(
7727c478bd9Sstevel@tonic-gate 				p->msg->msgiov, p->msg->msgiov_len, &reply);
7737c478bd9Sstevel@tonic-gate 		    if (reply)
7747c478bd9Sstevel@tonic-gate 			    free(reply);
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 		    p->wake_time = now + p->lifetime;
7777c478bd9Sstevel@tonic-gate 		}
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		if (p->wake_time < shortest_wait)
7807c478bd9Sstevel@tonic-gate 			shortest_wait = p->wake_time;
7817c478bd9Sstevel@tonic-gate 	}
7827c478bd9Sstevel@tonic-gate 	next_wake_time = shortest_wait;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate done:
7857c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&rereg_lock);
7867c478bd9Sstevel@tonic-gate 	return (more);
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate  * Removes the refresh registration for 'url'.
7917c478bd9Sstevel@tonic-gate  */
dereg_rereg(const char * url)7927c478bd9Sstevel@tonic-gate static unsigned short dereg_rereg(const char *url) {
7937c478bd9Sstevel@tonic-gate 	struct rereg_entry *p, *q;
7947c478bd9Sstevel@tonic-gate 	unsigned short lifetime = 0;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&rereg_lock);
7977c478bd9Sstevel@tonic-gate 	for (p = q = reregs; p; p = p->next) {
7987c478bd9Sstevel@tonic-gate 		if (slp_strcasecmp(p->url, url) == 0) {
7997c478bd9Sstevel@tonic-gate 			/* found it; remove it from the list */
8007c478bd9Sstevel@tonic-gate 			if (p == q) {
8017c478bd9Sstevel@tonic-gate 				/* first one on list */
8027c478bd9Sstevel@tonic-gate 				reregs = p->next;
8037c478bd9Sstevel@tonic-gate 			} else {
8047c478bd9Sstevel@tonic-gate 				q->next = p->next;
8057c478bd9Sstevel@tonic-gate 			}
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 			/* free the entry */
8087c478bd9Sstevel@tonic-gate 			lifetime = p->lifetime;
8097c478bd9Sstevel@tonic-gate 			free(p->url);
8107c478bd9Sstevel@tonic-gate 			/* free the message memory */
8117c478bd9Sstevel@tonic-gate 			free(p->msg->msgiov[0].iov_base);
8127c478bd9Sstevel@tonic-gate 			/* free the URL auth block */
8137c478bd9Sstevel@tonic-gate 			free(p->msg->msgiov[SLP_URL_AUTH].iov_base);
8147c478bd9Sstevel@tonic-gate 			/* free the attr auth block */
8157c478bd9Sstevel@tonic-gate 			free(p->msg->msgiov[SLP_ATTR_AUTH].iov_base);
8167c478bd9Sstevel@tonic-gate 			/* free the message iovec */
8177c478bd9Sstevel@tonic-gate 			free(p->msg->msgiov);
8187c478bd9Sstevel@tonic-gate 			/* finally, free the message structure */
8197c478bd9Sstevel@tonic-gate 			free(p->msg);
8207c478bd9Sstevel@tonic-gate 			free(p);
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 			goto done;
8237c478bd9Sstevel@tonic-gate 		}
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 		q = p;
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate done:
8297c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&rereg_lock);
8307c478bd9Sstevel@tonic-gate 	return (lifetime);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate  * Returns configured scopes in scopes. Caller should free *scopes
8357c478bd9Sstevel@tonic-gate  * when done. If the scope string is too long for an SLP string, the
8367c478bd9Sstevel@tonic-gate  * string is truncated.
8377c478bd9Sstevel@tonic-gate  */
find_SAscopes(char ** scopes)8387c478bd9Sstevel@tonic-gate static SLPError find_SAscopes(char **scopes) {
8397c478bd9Sstevel@tonic-gate 	SLPError err;
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	if ((err = slp_administrative_scopes(scopes, SLP_TRUE))
8427c478bd9Sstevel@tonic-gate 	    != SLP_OK) {
8437c478bd9Sstevel@tonic-gate 		return (err);
8447c478bd9Sstevel@tonic-gate 	}
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	/* Ensure string is not too long */
8477c478bd9Sstevel@tonic-gate 	if (strlen(*scopes) > SLP_MAX_STRINGLEN) {
8487c478bd9Sstevel@tonic-gate 		/* truncate the string */
8497c478bd9Sstevel@tonic-gate 		if ((*scopes)[SLP_MAX_STRINGLEN - 1] == ',') {
8507c478bd9Sstevel@tonic-gate 			/* scopes can't end with ',' */
8517c478bd9Sstevel@tonic-gate 			(*scopes)[SLP_MAX_STRINGLEN - 1] = 0;
8527c478bd9Sstevel@tonic-gate 		} else {
8537c478bd9Sstevel@tonic-gate 			(*scopes)[SLP_MAX_STRINGLEN] = 0;
8547c478bd9Sstevel@tonic-gate 		}
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	return (SLP_OK);
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate /*
8617c478bd9Sstevel@tonic-gate  * Does all the dirty work of freeing a msgiov.
8627c478bd9Sstevel@tonic-gate  */
free_msgiov(struct iovec * msgiov,int iovlen)8637c478bd9Sstevel@tonic-gate static void free_msgiov(struct iovec *msgiov, int iovlen) {
8647c478bd9Sstevel@tonic-gate 	/* free the message memory */
8657c478bd9Sstevel@tonic-gate 	free(msgiov[0].iov_base);
8667c478bd9Sstevel@tonic-gate 	/* free the URL auth block */
8677c478bd9Sstevel@tonic-gate 	free(msgiov[SLP_URL_AUTH].iov_base);
8687c478bd9Sstevel@tonic-gate 	if (iovlen == 4) {
8697c478bd9Sstevel@tonic-gate 		/* free the attr auth block */
8707c478bd9Sstevel@tonic-gate 		free(msgiov[SLP_ATTR_AUTH].iov_base);
8717c478bd9Sstevel@tonic-gate 	}
8727c478bd9Sstevel@tonic-gate 	/* free the message iovec */
8737c478bd9Sstevel@tonic-gate 	free(msgiov);
8747c478bd9Sstevel@tonic-gate }
875