/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file contains all functions pertaining to registrations:
* SLPReg
* SLPDereg
* SLPDelAttrs
*
* Each function talks only to the local slpd, and receives a SrvAck
* reply.
*
* These calls can operate in sync or async mode. Sync mode operates
* as follows:
* format params into a char *msg
* send this msg to slpd
* invoke the SLPRegReport callback with the error code found in the
* reply from slpd
* return
*
* Async mode operates as follows:
* format the params into a char *msg
* there is one thread per process which handles async regs
* make sure this thread is running
* the reg_thread monitors the global static reg_q for messages
* a queue message is represented as a struct reg_q_msg
* caller thread places the reg msg on the reg_q, and returns
* the reg_thread reads the message from the reg_q, and sends the
* msg to slpd
* the reg_thread then invokes the SLPRegReport callback with the error
* code found in the reply from slpd
* once started, the reg_thread manages registration refreshing.
* If there are no registrations to refresh, the thread exits.
*/
#include <stdio.h>
#include <stdlib.h>
#include <thread.h>
#include <synch.h>
#include <syslog.h>
#include <slp-internal.h>
#include <time.h>
/* Indices into a reg_msg iovec for auth blocks */
/* A registration / de-registration message */
struct reg_msg {
};
/*
* This is the message bundle passed to the reg thread via a queue.
*/
struct reg_q_msg {
void *cookie;
};
/*
* These structures and vars are used for automatic re-registering.
*/
static struct rereg_entry {
char *url;
unsigned short lifetime;
} *reregs;
/* Private Utility Routines */
static SLPBoolean check_reregs();
static unsigned short dereg_rereg(const char *);
void *, SLPRegReport *);
void *, SLPRegReport *);
static void reg_thread();
static SLPError start_reg_thr();
void *, SLPRegReport *);
unsigned short, const char *, const char *,
const char *, SLPBoolean, struct reg_msg **);
const char *, const char *, struct reg_msg **);
static void free_msgiov(struct iovec *, int);
/* Public API SA functionality */
const unsigned short usLifetime,
const char *pcSrvType,
char *pcScopeList;
return (SLP_PARAMETER_BAD);
}
return (SLP_PARAMETER_BAD);
}
return (err);
}
return (err);
/* format params into msg */
if ((err = packSrvReg(
return (err);
}
/* create a rereg message, with no attrs */
err = packSrvReg(
}
}
return (err);
}
char *m = NULL;
/* calculate the timestamp */
/* create the reg_msg */
return (SLP_MEMORY_ALLOC_FAILED);
}
/* compute the total messge length */
msgLen =
/* URL entry */
/* srv reg msg */
/*
* Allocate memory for all the message except the auth blocks.
* The iovec msgiov actually contains only pointers into this
* memory.
*/
goto error;
}
/*
* Create iovec for the msg. The iovec components are layed out thus:
* 0: header + URL
* 1: URL auth block count, URL auth block
* 2: attrs
* 3: attrs auth block count, attr auth block
*/
goto error;
}
!= SLP_OK)
goto error;
/* set fresh flag */
if (fresh)
slp_set_fresh(m);
/* URL entry */
len++; /* skip reserved byte in URL entry */
goto error;
/* save pointer to URL for signing */
goto error;
/* add auth blocks for URL */
goto error;
}
/* type, scopes, and attrs */
goto error;
goto error;
/* save pointer to attr for signing */
goto error;
/* length of 2nd portion is len - length of 1st portion */
/* add auth blocks for attrs */
goto error;
}
/* adjust msgLen with authblocks, and set header length */
/* make sure msgLen is valid */
if (msgLen > SLP_MAX_MSGLEN) {
goto error;
}
slp_set_length(m, msgLen);
return (SLP_OK);
if (m) free(m);
if (*msg) {
}
return (err);
}
char *pcScopeList;
return (SLP_PARAMETER_BAD);
}
return (SLP_PARAMETER_BAD);
}
!= SLP_OK) {
return (err);
}
return (err);
/* format params into msg */
!= SLP_OK) {
return (err);
}
(void) dereg_rereg(pURL);
}
return (err);
}
const char *pcAttrs,
char *pcScopeList;
return (SLP_PARAMETER_BAD);
}
return (SLP_PARAMETER_BAD);
}
!= SLP_OK) {
return (err);
}
return (err);
/* format params into msg */
!= SLP_OK) {
return (err);
}
}
char *m = NULL;
/* create the reg_msg */
return (SLP_MEMORY_ALLOC_FAILED);
}
/* compute the total message length */
msgLen =
/* URL entry */
return (SLP_MEMORY_ALLOC_FAILED);
}
/*
* Create iovec for the msg. The iovec components are layed out thus:
* 0: header + URL
* 1: URL auth block count, URL auth block
* 2: attrs
*/
goto error;
}
if ((err = slp_add_header(
goto error;
/* scopes */
goto error;
/* URL Entry */
len++; /* skip reserved byte in URL entry */
goto error;
/* save pointer to URL for signing */
goto error;
/* add auth blocks for URL */
goto error;
}
/* tag list */
goto error;
/* length of 2nd portion is len - length of 1st portion */
/* adjust msgLen with authblocks, and set header length */
/* make sure msgLen is valid */
if (msgLen > SLP_MAX_MSGLEN) {
goto error;
}
slp_set_length(m, msgLen);
return (SLP_OK);
if (m) free(m);
if (*msg) {
}
return (err);
}
/*
* Passes the packed message to the routines which talk to slpd.
*/
if (!slp_reg_thr_running)
goto reg_done;
else
/* If an error occurred, end_call() will not have happened */
return (err);
}
/*
* Put a reg message on the queue. Assumes reg_thread is running.
*/
return (SLP_MEMORY_ALLOC_FAILED);
}
}
/*
* Create a new reg_q and start the reg thread.
*/
int terr;
(void) mutex_lock(&start_lock);
/* make sure someone else hasn't already intialized the thread */
if (slp_reg_thr_running) {
goto start_done;
}
/* create the reg queue */
goto start_done;
}
/* start the reg thread */
if ((terr = thr_create(
0, NULL, (void *(*)(void *)) reg_thread,
"could not start thread: %s",
goto start_done;
}
slp_reg_thr_running = 1;
(void) mutex_unlock(&start_lock);
return (err);
}
/*
* This is what the permanent reg thread runs; it just sits in a loop
* monitoring the reg_q for new reg messages.
*
* To conserve resources,
* if there are no more registrations to refresh, it will exit.
*/
static void reg_thread() {
for (;;) {
/* get the next message from the queue */
/* timed out */
if (!check_reregs()) {
/* no more reregs; shut down this thread */
(void) mutex_lock(&start_lock);
slp_reg_thr_running = 0;
(void) mutex_unlock(&start_lock);
}
continue;
}
if (!rmsg)
continue;
/* got a new message */
(void) check_reregs();
}
}
/*
* Unpacks a SrvAck.
* 'reply' should point to the beginning of the header.
*/
char *p = reply + SLP_HDRLEN;
p += langlen;
return (err);
return (SLP_OK);
}
/*
* The dispatcher for SA messages. Sends a message to slpd, unpacks and
* dispatches the reply to the user callback.
*/
goto transaction_complete;
!= SLP_OK)
goto transaction_complete;
/* through with msg, so free it now */
goto transaction_complete;
/* the reg thread doubles as the consumer thread for SA calls */
if (reply) {
}
return (err);
}
/*
* Re-registration routines
*/
/*
* Adds the registration contained in 'msg' to the refresh registration
* list managed by reg_thread.
* Only registrations which are meant to be permanent are refreshed,
* so we only allow reg's with lifetime == SLP_LIFETIME_PERMANENT into
* the rereg table.
*/
unsigned short lifetime) {
if (lifetime != SLP_LIFETIME_MAXIMUM) {
return (SLP_OK);
}
(void) mutex_lock(&rereg_lock);
/* alloc a new rereg entry */
goto done;
}
goto done;
}
/* adjust the next wake time if necessary */
/* add the rereg to the list */
if (!reregs) {
/* first one */
goto done;
}
/* else add it to the beginning of the list */
done:
(void) mutex_unlock(&rereg_lock);
return (err);
}
/*
* Walks through the rereg list and re-registers any which will expire
* before the reg thread wakes up and checks again.
* Returns true if there are more reregs on the list, false if none.
*/
struct rereg_entry *p;
(void) mutex_lock(&rereg_lock);
if (!reregs) {
goto done;
}
char *reply;
/* rereg it, first recalculating signature */
(void) slp_send2slpd_iov(
if (reply)
}
if (p->wake_time < shortest_wait)
shortest_wait = p->wake_time;
}
done:
(void) mutex_unlock(&rereg_lock);
return (more);
}
/*
* Removes the refresh registration for 'url'.
*/
struct rereg_entry *p, *q;
unsigned short lifetime = 0;
(void) mutex_lock(&rereg_lock);
/* found it; remove it from the list */
if (p == q) {
/* first one on list */
} else {
}
/* free the entry */
/* free the message memory */
/* free the URL auth block */
/* free the attr auth block */
/* free the message iovec */
/* finally, free the message structure */
free(p);
goto done;
}
q = p;
}
done:
(void) mutex_unlock(&rereg_lock);
return (lifetime);
}
/*
* Returns configured scopes in scopes. Caller should free *scopes
* when done. If the scope string is too long for an SLP string, the
* string is truncated.
*/
!= SLP_OK) {
return (err);
}
/* Ensure string is not too long */
/* truncate the string */
/* scopes can't end with ',' */
} else {
(*scopes)[SLP_MAX_STRINGLEN] = 0;
}
}
return (SLP_OK);
}
/*
* Does all the dirty work of freeing a msgiov.
*/
/* free the message memory */
/* free the URL auth block */
if (iovlen == 4) {
/* free the attr auth block */
}
/* free the message iovec */
}