You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1677 lines
60 KiB
1677 lines
60 KiB
/***************************************************************************/
|
|
/* */
|
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
|
/* Protocol Version 2 */
|
|
/* */
|
|
/* File: slpd_knownda.c */
|
|
/* */
|
|
/* Abstract: Keeps track of known DAs */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Please submit patches to http://www.openslp.org */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (C) 2000 Caldera Systems, Inc */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or without */
|
|
/* modification, are permitted provided that the following conditions are */
|
|
/* met: */
|
|
/* */
|
|
/* Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* */
|
|
/* Redistributions in binary form must reproduce the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer in */
|
|
/* the documentation and/or other materials provided with the */
|
|
/* distribution. */
|
|
/* */
|
|
/* Neither the name of Caldera Systems nor the names of its */
|
|
/* contributors may be used to endorse or promote products derived */
|
|
/* from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
/* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
|
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */
|
|
/* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
|
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
|
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
|
|
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
/* */
|
|
/***************************************************************************/
|
|
|
|
#include "slpd.h"
|
|
|
|
/*=========================================================================*/
|
|
/* slpd includes */
|
|
/*=========================================================================*/
|
|
#include "slpd_knownda.h"
|
|
#include "slpd_property.h"
|
|
#include "slpd_database.h"
|
|
#include "slpd_socket.h"
|
|
#include "slpd_outgoing.h"
|
|
#include "slpd_log.h"
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
#include "slpd_spi.h"
|
|
#endif
|
|
|
|
/*=========================================================================*/
|
|
/* common code includes */
|
|
/*=========================================================================*/
|
|
#include "slp_xmalloc.h"
|
|
#include "slp_v1message.h"
|
|
#include "slp_utf8.h"
|
|
#include "slp_compare.h"
|
|
#include "slp_xid.h"
|
|
#include "slp_dhcp.h"
|
|
#include "slp_parse.h"
|
|
#include "slp_net.h"
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
#include "slp_auth.h"
|
|
#include "slp_spi.h"
|
|
#endif
|
|
|
|
#include <limits.h>
|
|
|
|
/*=========================================================================*/
|
|
SLPDatabase G_SlpdKnownDAs;
|
|
/* The database of DAAdverts from DAs known to slpd. */
|
|
/*=========================================================================*/
|
|
|
|
|
|
/*=========================================================================*/
|
|
int G_KnownDATimeSinceLastRefresh = 0;
|
|
/*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int MakeActiveDiscoveryRqst(int ismcast, SLPBuffer* buffer)
|
|
/* Pack a buffer with service:directory-agent SrvRqst *
|
|
* *
|
|
* Caller must free buffer *
|
|
*-------------------------------------------------------------------------*/
|
|
{
|
|
size_t size;
|
|
void* eh;
|
|
SLPMessage msg;
|
|
char* prlist = 0;
|
|
size_t prlistlen = 0;
|
|
int errorcode = 0;
|
|
SLPBuffer tmp = 0;
|
|
SLPBuffer result = *buffer;
|
|
|
|
/*-------------------------------------------------*/
|
|
/* Generate a DA service request buffer to be sent */
|
|
/*-------------------------------------------------*/
|
|
/* determine the size of the fixed portion of the SRVRQST */
|
|
size = 47; /* 14 bytes for the header */
|
|
/* 2 bytes for the prlistlen */
|
|
/* 2 bytes for the srvtype length */
|
|
/* 23 bytes for "service:directory-agent" srvtype */
|
|
/* 2 bytes for scopelistlen */
|
|
/* 2 bytes for predicatelen */
|
|
/* 2 bytes for sprstrlen */
|
|
|
|
/* figure out what our Prlist will be by going through our list of */
|
|
/* known DAs */
|
|
prlistlen = 0;
|
|
prlist = xmalloc(SLP_MAX_DATAGRAM_SIZE);
|
|
if ( prlist == 0 )
|
|
{
|
|
/* out of memory */
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
*prlist = 0;
|
|
/* Don't send active discoveries to DAs we already know about */
|
|
eh = SLPDKnownDAEnumStart();
|
|
if ( eh )
|
|
{
|
|
while ( 1 )
|
|
{
|
|
if ( SLPDKnownDAEnum(eh, &msg, &tmp) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
strcat(prlist,inet_ntoa(msg->peer.sin_addr));
|
|
strcat(prlist,",");
|
|
prlistlen = strlen(prlist);
|
|
}
|
|
|
|
SLPDKnownDAEnumEnd(eh);
|
|
}
|
|
|
|
/* Allocate the send buffer */
|
|
size += G_SlpdProperty.localeLen + prlistlen;
|
|
result = SLPBufferRealloc(result, size);
|
|
if ( result == 0 )
|
|
{
|
|
/* out of memory */
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*------------------------------------------------------------*/
|
|
/* Build a buffer containing the fixed portion of the SRVRQST */
|
|
/*------------------------------------------------------------*/
|
|
/*version*/
|
|
*(result->start) = 2;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_SRVRQST;
|
|
/*length*/
|
|
ToUINT24(result->start + 2, size);
|
|
/*flags*/
|
|
ToUINT16(result->start + 5, (ismcast ? SLP_FLAG_MCAST : 0));
|
|
/*ext offset*/
|
|
ToUINT24(result->start + 7,0);
|
|
/*xid*/
|
|
ToUINT16(result->start + 10, SLPXidGenerate()); /* TODO: generate a real XID */
|
|
/*lang tag len*/
|
|
ToUINT16(result->start + 12, G_SlpdProperty.localeLen);
|
|
/*lang tag*/
|
|
memcpy(result->start + 14,
|
|
G_SlpdProperty.locale,
|
|
G_SlpdProperty.localeLen);
|
|
result->curpos = result->start + G_SlpdProperty.localeLen + 14;
|
|
/* Prlist */
|
|
ToUINT16(result->curpos,prlistlen);
|
|
result->curpos = result->curpos + 2;
|
|
memcpy(result->curpos,prlist,prlistlen);
|
|
result->curpos = result->curpos + prlistlen;
|
|
/* service type */
|
|
ToUINT16(result->curpos,23);
|
|
result->curpos = result->curpos + 2;
|
|
/* 23 is the length of SLP_DA_SERVICE_TYPE */
|
|
memcpy(result->curpos,SLP_DA_SERVICE_TYPE,23);
|
|
result->curpos = result->curpos + 23;
|
|
/* scope list zero length */
|
|
ToUINT16(result->curpos,0);
|
|
result->curpos = result->curpos + 2;
|
|
/* predicate zero length */
|
|
ToUINT16(result->curpos,0);
|
|
result->curpos = result->curpos + 2;
|
|
/* spi list zero length */
|
|
ToUINT16(result->curpos,0);
|
|
result->curpos = result->curpos + 2;
|
|
|
|
*buffer = result;
|
|
|
|
FINISHED:
|
|
|
|
if ( prlist )
|
|
{
|
|
xfree(prlist);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void SLPDKnownDARegisterAll(SLPMessage daadvert, int immortalonly)
|
|
/* registers all services with specified DA */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPBuffer buf;
|
|
SLPMessage msg;
|
|
SLPSrvReg* srvreg;
|
|
SLPDSocket* sock;
|
|
SLPBuffer sendbuf = 0;
|
|
void* handle = 0;
|
|
|
|
/*---------------------------------------------------------------*/
|
|
/* Check to see if the database is empty and open an enumeration */
|
|
/* handle if it is not empty */
|
|
/*---------------------------------------------------------------*/
|
|
if ( SLPDDatabaseIsEmpty() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*--------------------------------------*/
|
|
/* Never do a Register All to ourselves */
|
|
/*--------------------------------------*/
|
|
if ( SLPCompareString(G_SlpdProperty.myUrlLen,
|
|
G_SlpdProperty.myUrl,
|
|
daadvert->body.daadvert.urllen,
|
|
daadvert->body.daadvert.url) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
handle = SLPDDatabaseEnumStart();
|
|
if ( handle == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*----------------------------------------------*/
|
|
/* Establish a new connection with the known DA */
|
|
/*----------------------------------------------*/
|
|
sock = SLPDOutgoingConnect(&(daadvert->peer.sin_addr));
|
|
if ( sock )
|
|
{
|
|
while ( 1 )
|
|
{
|
|
msg = SLPDDatabaseEnum(handle, &msg, &buf);
|
|
if ( msg == NULL ) break;
|
|
srvreg = &(msg->body.srvreg);
|
|
|
|
/*-----------------------------------------------*/
|
|
/* If so instructed, skip mortal registrations */
|
|
/*-----------------------------------------------*/
|
|
if ( immortalonly &&
|
|
srvreg->urlentry.lifetime < SLP_LIFETIME_MAXIMUM )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/*---------------------------------------------------------*/
|
|
/* Only register local (or static) registrations of scopes */
|
|
/* supported by peer DA */
|
|
/*---------------------------------------------------------*/
|
|
if ( ( srvreg->source == SLP_REG_SOURCE_LOCAL ||
|
|
srvreg->source == SLP_REG_SOURCE_STATIC ) &&
|
|
SLPIntersectStringList(srvreg->scopelistlen,
|
|
srvreg->scopelist,
|
|
srvreg->scopelistlen,
|
|
srvreg->scopelist) )
|
|
{
|
|
sendbuf = SLPBufferDup(buf);
|
|
if ( sendbuf )
|
|
{
|
|
/*--------------------------------------------------*/
|
|
/* link newly constructed buffer to socket sendlist */
|
|
/*--------------------------------------------------*/
|
|
SLPListLinkTail(&(sock->sendlist),(SLPListItem*)sendbuf);
|
|
if ( sock->state == STREAM_CONNECT_IDLE )
|
|
{
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SLPDDatabaseEnumEnd(handle);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int MakeSrvderegFromSrvReg(SLPMessage msg,
|
|
SLPBuffer inbuf,
|
|
SLPBuffer* outbuf)
|
|
/* Pack a buffer with a SrvDereg message using information from an existing
|
|
* SrvReg message
|
|
*
|
|
* Caller must free outbuf
|
|
*-------------------------------------------------------------------------*/
|
|
{
|
|
int size;
|
|
SLPBuffer sendbuf;
|
|
SLPSrvReg* srvreg;
|
|
|
|
srvreg = &(msg->body.srvreg);
|
|
|
|
/*-------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvdereg*/
|
|
/*-------------------------------------------------------------*/
|
|
size = msg->header.langtaglen + 18; /* 14 bytes for header */
|
|
/* 2 bytes for scopelen */
|
|
/* see below for URLEntry */
|
|
/* 2 bytes for taglist len */
|
|
if ( srvreg->urlentry.opaque )
|
|
{
|
|
size += srvreg->urlentry.opaquelen;
|
|
}
|
|
else
|
|
{
|
|
size += 6; /* +6 for the static portion of the url-entry */
|
|
size += srvreg->urlentry.urllen;
|
|
}
|
|
size += srvreg->scopelistlen;
|
|
/* taglistlen is always 0 */
|
|
|
|
*outbuf = sendbuf = SLPBufferAlloc(size);
|
|
if (*outbuf == NULL)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
/*----------------------*/
|
|
/* Construct a SrvDereg */
|
|
/*----------------------*/
|
|
/*version*/
|
|
*(sendbuf->start) = 2;
|
|
/*function id*/
|
|
*(sendbuf->start + 1) = SLP_FUNCT_SRVDEREG;
|
|
/*length*/
|
|
ToUINT24(sendbuf->start + 2, size);
|
|
/*flags*/
|
|
ToUINT16(sendbuf->start + 5,
|
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
|
/*ext offset*/
|
|
ToUINT24(sendbuf->start + 7,0);
|
|
/*xid*/
|
|
ToUINT16(sendbuf->start + 10,SLPXidGenerate());
|
|
/*lang tag len*/
|
|
ToUINT16(sendbuf->start + 12,msg->header.langtaglen);
|
|
/*lang tag*/
|
|
memcpy(sendbuf->start + 14,
|
|
msg->header.langtag,
|
|
msg->header.langtaglen);
|
|
sendbuf->curpos = sendbuf->start + 14 + msg->header.langtaglen;
|
|
|
|
/* scope list */
|
|
ToUINT16(sendbuf->curpos, srvreg->scopelistlen);
|
|
sendbuf->curpos = sendbuf->curpos + 2;
|
|
memcpy(sendbuf->curpos,srvreg->scopelist,srvreg->scopelistlen);
|
|
sendbuf->curpos = sendbuf->curpos + srvreg->scopelistlen;
|
|
/* the urlentry */
|
|
#ifdef ENABLE_SLPv1
|
|
if ( srvreg->urlentry.opaque == 0 )
|
|
{
|
|
/* url-entry reserved */
|
|
*sendbuf->curpos = 0;
|
|
sendbuf->curpos += 1;
|
|
/* url-entry lifetime */
|
|
ToUINT16(sendbuf->curpos,srvreg->urlentry.lifetime);
|
|
sendbuf->curpos = sendbuf->curpos + 2;
|
|
/* url-entry urllen */
|
|
ToUINT16(sendbuf->curpos,srvreg->urlentry.urllen);
|
|
sendbuf->curpos += 2;
|
|
/* url-entry url */
|
|
memcpy(sendbuf->curpos,
|
|
srvreg->urlentry.url,
|
|
srvreg->urlentry.urllen);
|
|
sendbuf->curpos += srvreg->urlentry.urllen;
|
|
/* url-entry authcount */
|
|
*sendbuf->curpos = 0;
|
|
sendbuf->curpos += 1;
|
|
}
|
|
else
|
|
#endif /* ENABLE_SLPv1 */
|
|
{
|
|
memcpy(sendbuf->curpos,
|
|
srvreg->urlentry.opaque,
|
|
srvreg->urlentry.opaquelen);
|
|
sendbuf->curpos += srvreg->urlentry.opaquelen;
|
|
}
|
|
|
|
/* taglist (always 0) */
|
|
ToUINT16(sendbuf->curpos,0);
|
|
sendbuf->curpos += 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void SLPDKnownDADeregisterAll(SLPMessage daadvert)
|
|
/* de-registers all services with specified DA */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPBuffer buf;
|
|
SLPMessage msg;
|
|
SLPSrvReg* srvreg;
|
|
SLPDSocket* sock;
|
|
SLPBuffer sendbuf = 0;
|
|
void* handle = 0;
|
|
|
|
/*---------------------------------------------------------------*/
|
|
/* Check to see if the database is empty and open an enumeration */
|
|
/* handle if it is not empty */
|
|
/*---------------------------------------------------------------*/
|
|
if ( SLPDDatabaseIsEmpty() )
|
|
{
|
|
return;
|
|
}
|
|
handle = SLPDDatabaseEnumStart();
|
|
if ( handle == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Establish a new connection with the known DA */
|
|
sock = SLPDOutgoingConnect(&(daadvert->peer.sin_addr));
|
|
if ( sock )
|
|
{
|
|
while ( 1 )
|
|
{
|
|
msg = SLPDDatabaseEnum(handle, &msg, &buf);
|
|
if ( msg == NULL ) break;
|
|
srvreg = &(msg->body.srvreg);
|
|
|
|
/*-------------------------------------------------*/
|
|
/* Deregister all local (and static) registrations */
|
|
/*-------------------------------------------------*/
|
|
if ( srvreg->source == SLP_REG_SOURCE_LOCAL ||
|
|
srvreg->source == SLP_REG_SOURCE_STATIC )
|
|
{
|
|
if(MakeSrvderegFromSrvReg(msg,buf,&sendbuf) == 0)
|
|
{
|
|
/*--------------------------------------------------*/
|
|
/* link newly constructed buffer to socket sendlist */
|
|
/*--------------------------------------------------*/
|
|
SLPListLinkTail(&(sock->sendlist),(SLPListItem*)sendbuf);
|
|
if ( sock->state == STREAM_CONNECT_IDLE )
|
|
{
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SLPDDatabaseEnumEnd(handle);
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int SLPDKnownDAFromDHCP()
|
|
/* Queries DHCP for configured DA's. */
|
|
/* */
|
|
/* returns zero on success, Non-zero on failure */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPBuffer buf;
|
|
DHCPContext ctx;
|
|
SLPDSocket* sock;
|
|
struct in_addr daaddr;
|
|
unsigned char * alp;
|
|
unsigned char dhcpOpts[] = {TAG_SLP_SCOPE, TAG_SLP_DA};
|
|
|
|
*ctx.scopelist = 0;
|
|
ctx.addrlistlen = 0;
|
|
|
|
DHCPGetOptionInfo(dhcpOpts, sizeof(dhcpOpts), DHCPParseSLPTags, &ctx);
|
|
|
|
alp = ctx.addrlist;
|
|
while(ctx.addrlistlen >= 4)
|
|
{
|
|
memcpy(&daaddr.s_addr, alp, 4);
|
|
if (daaddr.s_addr)
|
|
{
|
|
/*--------------------------------------------------------
|
|
Get an outgoing socket to the DA and set it up to make
|
|
the service:directoryagent request
|
|
--------------------------------------------------------*/
|
|
sock = SLPDOutgoingConnect(&daaddr);
|
|
if (sock)
|
|
{
|
|
buf = 0;
|
|
if (MakeActiveDiscoveryRqst(0,&buf) == 0)
|
|
{
|
|
if (sock->state == STREAM_CONNECT_IDLE)
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
SLPListLinkTail(&(sock->sendlist),(SLPListItem*)buf);
|
|
if (sock->state == STREAM_CONNECT_IDLE)
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
}
|
|
}
|
|
}
|
|
ctx.addrlistlen -= 4;
|
|
alp += 4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
int SLPKnownDAFromProperties()
|
|
/* Queries static configuration for DA's. */
|
|
/* */
|
|
/* returns zero on success, Non-zero on failure */
|
|
/*=========================================================================*/
|
|
{
|
|
char* temp;
|
|
char* tempend;
|
|
char* slider1;
|
|
char* slider2;
|
|
struct hostent* he;
|
|
struct in_addr daaddr;
|
|
SLPDSocket* sock;
|
|
SLPBuffer buf;
|
|
|
|
if (G_SlpdProperty.DAAddresses && *G_SlpdProperty.DAAddresses)
|
|
{
|
|
temp = slider1 = xstrdup(G_SlpdProperty.DAAddresses);
|
|
if (temp)
|
|
{
|
|
tempend = temp + strlen(temp);
|
|
while (slider1 < tempend)
|
|
{
|
|
while (*slider1 && *slider1 == ' ') slider1++;
|
|
slider2 = slider1;
|
|
while (*slider2 && *slider2 != ',') slider2++;
|
|
*slider2++ = 0;
|
|
|
|
daaddr.s_addr = 0;
|
|
if(inet_aton(slider1, &daaddr) == 0)
|
|
{
|
|
he = gethostbyname(slider1);
|
|
if (he)
|
|
daaddr.s_addr = *((unsigned int*)(he->h_addr_list[0]));
|
|
}
|
|
|
|
if(daaddr.s_addr)
|
|
{
|
|
/*--------------------------------------------------------*/
|
|
/* Get an outgoing socket to the DA and set it up to make */
|
|
/* the service:directoryagent request */
|
|
/*--------------------------------------------------------*/
|
|
sock = SLPDOutgoingConnect(&daaddr);
|
|
if (sock)
|
|
{
|
|
buf = 0;
|
|
if (MakeActiveDiscoveryRqst(0,&buf) == 0)
|
|
{
|
|
if (sock->state == STREAM_CONNECT_IDLE)
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
SLPListLinkTail(&(sock->sendlist),(SLPListItem*)buf);
|
|
if (sock->state == STREAM_CONNECT_IDLE)
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
}
|
|
}
|
|
}
|
|
slider1 = slider2;
|
|
}
|
|
xfree(temp);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
int SLPDKnownDAInit()
|
|
/* Initializes the KnownDA list. Removes all entries and adds entries */
|
|
/* that are statically configured. Adds entries configured through DHCP. */
|
|
/* */
|
|
/* returns zero on success, Non-zero on failure */
|
|
/*=========================================================================*/
|
|
{
|
|
/*--------------------------------------*/
|
|
/* Set initialize the DAAdvert database */
|
|
/*--------------------------------------*/
|
|
SLPDatabaseInit(&G_SlpdKnownDAs);
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
/* Added statically configured DAs to the Known DA List by sending */
|
|
/* active DA discovery requests directly to them */
|
|
/*-----------------------------------------------------------------*/
|
|
SLPKnownDAFromProperties();
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
/* Discover DHCP DA's and add them to the active discovery list. */
|
|
/*-----------------------------------------------------------------*/
|
|
SLPDKnownDAFromDHCP();
|
|
|
|
/*----------------------------------------*/
|
|
/* Lastly, Perform first active discovery */
|
|
/*----------------------------------------*/
|
|
SLPDKnownDAActiveDiscovery(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int SLPDKnownDADeinit()
|
|
/* Deinitializes the KnownDA list. Removes all entries and deregisters */
|
|
/* all services. */
|
|
/* */
|
|
/* returns zero on success, Non-zero on failure */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
if ( dh )
|
|
{
|
|
/*------------------------------------*/
|
|
/* Unregister all local registrations */
|
|
/*------------------------------------*/
|
|
while ( 1 )
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if ( entry == NULL ) break;
|
|
|
|
SLPDKnownDADeregisterAll(entry->msg);
|
|
}
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
SLPDatabaseDeinit(&G_SlpdKnownDAs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int SLPDKnownDAAdd(SLPMessage msg, SLPBuffer buf)
|
|
/* Adds a DA to the known DA list if it is new, removes it if DA is going */
|
|
/* down or adjusts entry if DA changed. */
|
|
/* */
|
|
/* msg (IN) DAAdvert Message descriptor */
|
|
/* */
|
|
/* buf (IN) The DAAdvert message buffer */
|
|
/* */
|
|
/* returns Zero on success, Non-zero on error */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseEntry* entry;
|
|
SLPDAAdvert* entrydaadvert;
|
|
SLPDAAdvert* daadvert;
|
|
struct in_addr daaddr;
|
|
SLPParsedSrvUrl* parsedurl = NULL;
|
|
int result = 0;
|
|
SLPDatabaseHandle dh = NULL;
|
|
|
|
dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
if ( dh == NULL )
|
|
{
|
|
result = SLP_ERROR_INTERNAL_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
/* daadvert is the DAAdvert message being added */
|
|
daadvert = &(msg->body.daadvert);
|
|
|
|
|
|
/* --------------------------------------------------------
|
|
* Make sure that the peer address in the DAAdvert matches
|
|
* the host in the DA service URL.
|
|
*---------------------------------------------------------
|
|
*/
|
|
if (SLPParseSrvUrl(daadvert->urllen,
|
|
daadvert->url,
|
|
&parsedurl))
|
|
{
|
|
/* could not parse the DA service url */
|
|
result = SLP_ERROR_PARSE_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
if (SLPNetResolveHostToAddr(parsedurl->host,&daaddr))
|
|
{
|
|
/* Unable to resolve the host in the DA advert to an address */
|
|
xfree(parsedurl);
|
|
result = SLP_ERROR_PARSE_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
/* free the parsed url created in call to SLPParseSrvUrl() */
|
|
xfree(parsedurl);
|
|
/* set the peer address in the DAAdvert message so that it matches
|
|
* the address the DA service URL resolves to
|
|
*/
|
|
msg->peer.sin_addr = daaddr;
|
|
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* Check to see if there is already an identical entry */
|
|
/*-----------------------------------------------------*/
|
|
while ( 1 )
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if ( entry == NULL ) break;
|
|
|
|
/* entrydaadvert is the DAAdvert message from the database */
|
|
entrydaadvert = &(entry->msg->body.daadvert);
|
|
|
|
/* Assume DAs are identical if their URLs match */
|
|
if ( SLPCompareString(entrydaadvert->urllen,
|
|
entrydaadvert->url,
|
|
daadvert->urllen,
|
|
daadvert->url) == 0 )
|
|
{
|
|
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if ( G_SlpdProperty.checkSourceAddr &&
|
|
memcmp(&(entry->msg->peer.sin_addr),
|
|
&(msg->peer.sin_addr),
|
|
sizeof(struct in_addr)) )
|
|
{
|
|
SLPDatabaseClose(dh);
|
|
result = SLP_ERROR_AUTHENTICATION_FAILED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
/* make sure an unauthenticated DAAdvert can't replace */
|
|
/* an authenticated one */
|
|
if ( entrydaadvert->authcount &&
|
|
entrydaadvert->authcount != daadvert->authcount )
|
|
{
|
|
SLPDatabaseClose(dh);
|
|
result = SLP_ERROR_AUTHENTICATION_FAILED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
#endif
|
|
|
|
if ( daadvert->bootstamp != 0 &&
|
|
daadvert->bootstamp <= entrydaadvert->bootstamp )
|
|
{
|
|
/* Advertising DA must have went down then came back up */
|
|
SLPDKnownDARegisterAll(msg,0);
|
|
}
|
|
|
|
/* Remove the entry that is the same as the advertised entry */
|
|
/* so that we can put the new advertised entry back in */
|
|
SLPDatabaseRemove(dh,entry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Make sure the DA is not dying */
|
|
if (daadvert->bootstamp != 0)
|
|
{
|
|
if ( entry == 0 )
|
|
{
|
|
/* create a new database entry using the DAAdvert message */
|
|
entry = SLPDatabaseEntryCreate(msg,buf);
|
|
if (entry)
|
|
{
|
|
SLPDatabaseAdd(dh, entry);
|
|
|
|
/* register all the services we know about with this new DA */
|
|
SLPDKnownDARegisterAll(msg,0);
|
|
|
|
/* log the addition of a new DA */
|
|
SLPDLogDAAdvertisement("Addition",entry);
|
|
}
|
|
else
|
|
{
|
|
/* Could not create a new entry */
|
|
result = SLP_ERROR_INTERNAL_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The advertising DA is not new to us, but the old entry */
|
|
/* has been deleted from our database so that the new entry */
|
|
/* with its up to date time stamp can be put back in. */
|
|
/* create a new database entry using the DAAdvert message */
|
|
entry = SLPDatabaseEntryCreate(msg,buf);
|
|
if (entry)
|
|
{
|
|
SLPDatabaseAdd(dh, entry);
|
|
}
|
|
else
|
|
{
|
|
/* Could not create a new entry */
|
|
result = SLP_ERROR_INTERNAL_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
/* DA is dying */
|
|
if (entry)
|
|
{
|
|
/* Dying DA was found in our KnownDA database. Log that it
|
|
* was removed.
|
|
*/
|
|
SLPDLogDAAdvertisement("Removed",entry);
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
/* If we are here, we need to cleanup the message descriptor and the */
|
|
/* message buffer because they were not added to the database and not */
|
|
/* cleaning them up would result in a memory leak */
|
|
/* We also need to make sure the Database handle is closed. */
|
|
SLPMessageFree(msg);
|
|
SLPBufferFree(buf);
|
|
if (dh) SLPDatabaseClose(dh);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDARemove(struct in_addr* addr)
|
|
/* Removes known DAs that sent DAAdverts from the specified in_addr */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
|
|
dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
if ( dh )
|
|
{
|
|
/*-----------------------------------------------------*/
|
|
/* Check to see if there is already an identical entry */
|
|
/*-----------------------------------------------------*/
|
|
while ( 1 )
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if ( entry == NULL ) break;
|
|
|
|
/* Assume DAs are identical if their peer match */
|
|
if ( memcmp(addr,&(entry->msg->peer.sin_addr),sizeof(*addr)) == 0 )
|
|
{
|
|
SLPDatabaseRemove(dh,entry);
|
|
SLPDLogDAAdvertisement("Removal",entry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void* SLPDKnownDAEnumStart()
|
|
/* Start an enumeration of all Known DAs */
|
|
/* */
|
|
/* Returns: An enumeration handle that is passed to subsequent calls to */
|
|
/* SLPDKnownDAEnum(). Returns NULL on failure. Returned */
|
|
/* enumeration handle (if not NULL) must be passed to */
|
|
/* SLPDKnownDAEnumEnd() when you are done with it. */
|
|
/*=========================================================================*/
|
|
{
|
|
return SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
SLPMessage SLPDKnownDAEnum(void* eh, SLPMessage* msg, SLPBuffer* buf)
|
|
/* Enumerate through all Known DAs */
|
|
/* */
|
|
/* eh (IN) pointer to opaque data that is used to maintain */
|
|
/* enumerate entries. Pass in a pointer to NULL to start */
|
|
/* enumeration. */
|
|
/* */
|
|
/* msg (OUT) pointer to the DAAdvert message descriptor */
|
|
/* */
|
|
/* buf (OUT) pointer to the DAAdvert message buffer */
|
|
/* */
|
|
/* returns: Pointer to enumerated entry or NULL if end of enumeration */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseEntry* entry;
|
|
entry = SLPDatabaseEnum((SLPDatabaseHandle) eh);
|
|
if ( entry )
|
|
{
|
|
*msg = entry->msg;
|
|
*buf = entry->buf;
|
|
}
|
|
else
|
|
{
|
|
*msg = 0;
|
|
*buf = 0;
|
|
}
|
|
|
|
return *msg;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDAEnumEnd(void* eh)
|
|
/* End an enumeration started by SLPDKnownDAEnumStart() */
|
|
/* */
|
|
/* Parameters: eh (IN) The enumeration handle returned by */
|
|
/* SLPDKnownDAEnumStart() */
|
|
/*=========================================================================*/
|
|
{
|
|
if ( eh )
|
|
{
|
|
SLPDatabaseClose((SLPDatabaseHandle)eh);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int SLPDKnownDAGenerateMyDAAdvert(int errorcode,
|
|
int deadda,
|
|
int xid,
|
|
SLPBuffer* sendbuf)
|
|
/* Pack a buffer with a DAAdvert using information from a SLPDAentry */
|
|
/* */
|
|
/* errorcode (IN) the errorcode for the DAAdvert */
|
|
/* */
|
|
/* xid (IN) the xid to for the DAAdvert */
|
|
/* */
|
|
/* daentry (IN) pointer to the daentry that contains the rest of the info */
|
|
/* to make the DAAdvert */
|
|
/* */
|
|
/* sendbuf (OUT) pointer to the SLPBuffer that will be packed with a */
|
|
/* DAAdvert */
|
|
/* */
|
|
/* returns: zero on success, non-zero on error */
|
|
/*=========================================================================*/
|
|
{
|
|
int size;
|
|
SLPBuffer result = *sendbuf;
|
|
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
int daadvertauthlen = 0;
|
|
unsigned char* daadvertauth = 0;
|
|
int spistrlen = 0;
|
|
char* spistr = 0;
|
|
|
|
G_SlpdProperty.DATimestamp += 1;
|
|
|
|
if ( G_SlpdProperty.securityEnabled )
|
|
{
|
|
SLPSpiGetDefaultSPI(G_SlpdSpiHandle,
|
|
SLPSPI_KEY_TYPE_PRIVATE,
|
|
&spistrlen,
|
|
&spistr);
|
|
|
|
SLPAuthSignDAAdvert(G_SlpdSpiHandle,
|
|
spistrlen,
|
|
spistr,
|
|
G_SlpdProperty.DATimestamp,
|
|
G_SlpdProperty.myUrlLen,
|
|
G_SlpdProperty.myUrl,
|
|
0,
|
|
0,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes,
|
|
spistrlen,
|
|
spistr,
|
|
&daadvertauthlen,
|
|
&daadvertauth);
|
|
}
|
|
#else
|
|
G_SlpdProperty.DATimestamp += 1;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvrply */
|
|
/*-------------------------------------------------------------*/
|
|
size = G_SlpdProperty.localeLen + 29; /* 14 bytes for header */
|
|
/* 2 errorcode */
|
|
/* 4 bytes for timestamp */
|
|
/* 2 bytes for url len */
|
|
/* 2 bytes for scope list len */
|
|
/* 2 bytes for attr list len */
|
|
/* 2 bytes for spi str len */
|
|
/* 1 byte for authblock count */
|
|
size += G_SlpdProperty.myUrlLen;
|
|
size += G_SlpdProperty.useScopesLen;
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
size += spistrlen;
|
|
size += daadvertauthlen;
|
|
#endif
|
|
|
|
result = SLPBufferRealloc(result, size);
|
|
if ( result == 0 )
|
|
{
|
|
/* Out of memory, what should we do here! */
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Add the header */
|
|
/*----------------*/
|
|
/*version*/
|
|
*(result->start) = 2;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_DAADVERT;
|
|
/*length*/
|
|
ToUINT24(result->start + 2, size);
|
|
/*flags*/
|
|
ToUINT16(result->start + 5,
|
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
|
/*ext offset*/
|
|
ToUINT24(result->start + 7,0);
|
|
/*xid*/
|
|
ToUINT16(result->start + 10,xid);
|
|
/*lang tag len*/
|
|
ToUINT16(result->start + 12, G_SlpdProperty.localeLen);
|
|
/*lang tag*/
|
|
memcpy(result->start + 14,
|
|
G_SlpdProperty.locale,
|
|
G_SlpdProperty.localeLen);
|
|
result->curpos = result->start + 14 + G_SlpdProperty.localeLen;
|
|
|
|
/*--------------------------*/
|
|
/* Add rest of the DAAdvert */
|
|
/*--------------------------*/
|
|
/* error code */
|
|
ToUINT16(result->curpos,errorcode);
|
|
result->curpos = result->curpos + 2;
|
|
if ( errorcode == 0 )
|
|
{
|
|
/* timestamp */
|
|
if ( deadda )
|
|
{
|
|
ToUINT32(result->curpos,0);
|
|
}
|
|
else
|
|
{
|
|
ToUINT32(result->curpos,G_SlpdProperty.DATimestamp);
|
|
}
|
|
result->curpos = result->curpos + 4;
|
|
/* url len */
|
|
ToUINT16(result->curpos, G_SlpdProperty.myUrlLen);
|
|
result->curpos = result->curpos + 2;
|
|
/* url */
|
|
memcpy(result->curpos,
|
|
G_SlpdProperty.myUrl,
|
|
G_SlpdProperty.myUrlLen);
|
|
result->curpos = result->curpos + G_SlpdProperty.myUrlLen;
|
|
/* scope list len */
|
|
ToUINT16(result->curpos, G_SlpdProperty.useScopesLen);
|
|
result->curpos = result->curpos + 2;
|
|
/* scope list */
|
|
memcpy(result->curpos,
|
|
G_SlpdProperty.useScopes,
|
|
G_SlpdProperty.useScopesLen);
|
|
result->curpos = result->curpos + G_SlpdProperty.useScopesLen;
|
|
/* attr list len */
|
|
ToUINT16(result->curpos, 0);
|
|
result->curpos = result->curpos + 2;
|
|
/* attr list */
|
|
/* memcpy(result->start, ???, 0); */
|
|
/* result->curpos = result->curpos + daentry->attrlistlen; */
|
|
/* SPI List */
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
ToUINT16(result->curpos,spistrlen);
|
|
result->curpos = result->curpos + 2;
|
|
memcpy(result->curpos,spistr,spistrlen);
|
|
result->curpos = result->curpos + spistrlen;
|
|
#else
|
|
ToUINT16(result->curpos,0);
|
|
result->curpos = result->curpos + 2;
|
|
#endif
|
|
|
|
|
|
|
|
/* authblock count */
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if ( daadvertauth )
|
|
{
|
|
/* authcount */
|
|
*(result->curpos) = 1;
|
|
result->curpos = result->curpos + 1;
|
|
/* authblock */
|
|
memcpy(result->curpos,daadvertauth,daadvertauthlen);
|
|
result->curpos = result->curpos + daadvertauthlen;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
*(result->curpos) = 0;
|
|
result->curpos = result->curpos + 1;
|
|
}
|
|
}
|
|
|
|
FINISHED:
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if ( daadvertauth ) xfree(daadvertauth);
|
|
if ( spistr ) xfree(spistr);
|
|
#endif
|
|
*sendbuf = result;
|
|
|
|
return errorcode;
|
|
}
|
|
|
|
|
|
#if defined(ENABLE_SLPv1)
|
|
/*=========================================================================*/
|
|
int SLPDKnownDAGenerateMyV1DAAdvert(int errorcode,
|
|
int encoding,
|
|
unsigned int xid,
|
|
SLPBuffer* sendbuf)
|
|
/* Pack a buffer with a v1 DAAdvert using information from a SLPDAentry */
|
|
/* */
|
|
/* errorcode (IN) the errorcode for the DAAdvert */
|
|
/* */
|
|
/* encoding (IN) the SLPv1 language encoding for the DAAdvert */
|
|
/* */
|
|
/* xid (IN) the xid to for the DAAdvert */
|
|
/* */
|
|
/* sendbuf (OUT) pointer to the SLPBuffer that will be packed with a */
|
|
/* DAAdvert */
|
|
/* */
|
|
/* returns: zero on success, non-zero on error */
|
|
/*=========================================================================*/
|
|
{
|
|
int size = 0;
|
|
int urllen = INT_MAX;
|
|
int scopelistlen = INT_MAX;
|
|
SLPBuffer result = *sendbuf;
|
|
|
|
/*-------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvrply */
|
|
/*-------------------------------------------------------------*/
|
|
size = 18; /* 12 bytes for header */
|
|
/* 2 errorcode */
|
|
/* 2 bytes for url len */
|
|
/* 2 bytes for scope list len */
|
|
|
|
if ( !errorcode )
|
|
{
|
|
errorcode = SLPv1ToEncoding(0,
|
|
&urllen,
|
|
encoding,
|
|
G_SlpdProperty.myUrl,
|
|
G_SlpdProperty.myUrlLen);
|
|
if ( !errorcode )
|
|
{
|
|
size += urllen;
|
|
#ifndef FAKE_UNSCOPED_DA
|
|
errorcode = SLPv1ToEncoding(0, &scopelistlen,
|
|
encoding,
|
|
G_SlpdProperty.useScopes,
|
|
G_SlpdProperty.useScopesLen);
|
|
#else
|
|
scopelistlen = 0; /* pretend that we're unscoped */
|
|
#endif
|
|
if ( !errorcode )
|
|
{
|
|
size += scopelistlen;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* don't add these */
|
|
urllen = scopelistlen = 0;
|
|
}
|
|
|
|
result = SLPBufferRealloc(result, size);
|
|
if ( result == 0 )
|
|
{
|
|
/* TODO: out of memory, what should we do here! */
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Add the header */
|
|
/*----------------*/
|
|
/*version*/
|
|
*(result->start) = 1;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_DAADVERT;
|
|
/*length*/
|
|
ToUINT16(result->start + 2, size);
|
|
/*flags - TODO we have to handle monoling and all that crap */
|
|
ToUINT16(result->start + 4,
|
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0));
|
|
/*dialect*/
|
|
*(result->start + 5) = 0;
|
|
/*language code*/
|
|
if ( G_SlpdProperty.locale )
|
|
{
|
|
memcpy(result->start + 6, G_SlpdProperty.locale, 2);
|
|
}
|
|
ToUINT16(result->start + 8, encoding);
|
|
/*xid*/
|
|
ToUINT16(result->start + 10,xid);
|
|
|
|
result->curpos = result->start + 12;
|
|
|
|
/*--------------------------*/
|
|
/* Add rest of the DAAdvert */
|
|
/*--------------------------*/
|
|
/* error code */
|
|
ToUINT16(result->curpos,errorcode);
|
|
result->curpos = result->curpos + 2;
|
|
ToUINT16(result->curpos, urllen);
|
|
result->curpos = result->curpos + 2;
|
|
/* url */
|
|
SLPv1ToEncoding(result->curpos,
|
|
&urllen,
|
|
encoding,
|
|
G_SlpdProperty.myUrl,
|
|
G_SlpdProperty.myUrlLen);
|
|
result->curpos = result->curpos + urllen;
|
|
/* scope list len */
|
|
ToUINT16(result->curpos, scopelistlen);
|
|
result->curpos = result->curpos + 2;
|
|
/* scope list */
|
|
#ifndef FAKE_UNSCOPED_DA
|
|
SLPv1ToEncoding(result->curpos,
|
|
&scopelistlen,
|
|
encoding,
|
|
G_SlpdProperty.useScopes,
|
|
G_SlpdProperty.useScopesLen);
|
|
#endif
|
|
|
|
result->curpos = result->curpos + scopelistlen;
|
|
|
|
FINISHED:
|
|
*sendbuf = result;
|
|
|
|
return errorcode;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDAEcho(SLPMessage msg, SLPBuffer buf)
|
|
/* Echo a srvreg message to a known DA */
|
|
/* */
|
|
/* msg (IN) the SrvReg message descriptor */
|
|
/* */
|
|
/* buf (IN) the SrvReg message buffer to echo */
|
|
/* */
|
|
/* Returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPBuffer dup;
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
SLPDAAdvert* entrydaadvert;
|
|
SLPDSocket* sock;
|
|
const char* msgscope;
|
|
int msgscopelen;
|
|
|
|
/* Do not echo registrations if we are a DA unless they were made */
|
|
/* local through the API! */
|
|
if ( G_SlpdProperty.isDA && !ISLOCAL(msg->peer.sin_addr) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( msg->header.functionid == SLP_FUNCT_SRVREG )
|
|
{
|
|
msgscope = msg->body.srvreg.scopelist;
|
|
msgscopelen = msg->body.srvreg.scopelistlen;
|
|
}
|
|
else if ( msg->header.functionid == SLP_FUNCT_SRVDEREG )
|
|
{
|
|
msgscope = msg->body.srvdereg.scopelist;
|
|
msgscopelen = msg->body.srvdereg.scopelistlen;
|
|
}
|
|
else
|
|
{
|
|
/* We only echo SRVREG and SRVDEREG */
|
|
return;
|
|
}
|
|
|
|
dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
if ( dh )
|
|
{
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* Check to see if there is already an identical entry */
|
|
/*-----------------------------------------------------*/
|
|
while ( 1 )
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if ( entry == NULL ) break;
|
|
|
|
/* entrydaadvert is the DAAdvert message from the database */
|
|
entrydaadvert = &(entry->msg->body.daadvert);
|
|
|
|
/* Send to all DAs that have matching scope */
|
|
if ( SLPIntersectStringList(msgscopelen,
|
|
msgscope,
|
|
entrydaadvert->scopelistlen,
|
|
entrydaadvert->scopelist) )
|
|
{
|
|
/* Do not echo to ourselves if we are a DA*/
|
|
if ( G_SlpdProperty.isDA &&
|
|
SLPCompareString(G_SlpdProperty.myUrlLen,
|
|
G_SlpdProperty.myUrl,
|
|
entrydaadvert->urllen,
|
|
entrydaadvert->url) == 0 )
|
|
{
|
|
/* don't do anything because it makes no sense to echo */
|
|
/* to myself */
|
|
}
|
|
else
|
|
{
|
|
/*------------------------------------------*/
|
|
/* Load the socket with the message to send */
|
|
/*------------------------------------------*/
|
|
sock = SLPDOutgoingConnect(&(entry->msg->peer.sin_addr));
|
|
if ( sock )
|
|
{
|
|
dup = SLPBufferDup(buf);
|
|
if ( dup )
|
|
{
|
|
SLPListLinkTail(&(sock->sendlist),(SLPListItem*)dup);
|
|
if ( sock->state == STREAM_CONNECT_IDLE )
|
|
{
|
|
sock->state = STREAM_WRITE_FIRST;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sock->state = SOCKET_CLOSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDAActiveDiscovery(int seconds)
|
|
/* Add a socket to the outgoing list to do active DA discovery SrvRqst */
|
|
/* */
|
|
/* seconds (IN) number of seconds that expired since last call */
|
|
/* */
|
|
/* Returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
struct in_addr peeraddr;
|
|
SLPDSocket* sock;
|
|
|
|
/* Check to see if we should perform active DA detection */
|
|
if ( G_SlpdProperty.DAActiveDiscoveryInterval == 0 )
|
|
{
|
|
return;
|
|
}
|
|
/* When activeDiscoveryXmits is < 0 then we should not xmit any more */
|
|
if (G_SlpdProperty.activeDiscoveryXmits < 0)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
if ( G_SlpdProperty.nextActiveDiscovery <= 0 )
|
|
{
|
|
if ( G_SlpdProperty.activeDiscoveryXmits == 0)
|
|
{
|
|
if (G_SlpdProperty.DAActiveDiscoveryInterval == 1)
|
|
{/* ensures xmit on first call */
|
|
/* don't xmit any more */
|
|
G_SlpdProperty.activeDiscoveryXmits = -1;
|
|
}
|
|
else
|
|
{
|
|
G_SlpdProperty.nextActiveDiscovery = G_SlpdProperty.DAActiveDiscoveryInterval;
|
|
G_SlpdProperty.activeDiscoveryXmits = 3;
|
|
}
|
|
}
|
|
|
|
G_SlpdProperty.activeDiscoveryXmits --;
|
|
|
|
/*--------------------------------------------------*/
|
|
/* Create new DATAGRAM socket with appropriate peer */
|
|
/*--------------------------------------------------*/
|
|
if ( G_SlpdProperty.isBroadcastOnly == 0 )
|
|
{
|
|
peeraddr.s_addr = htonl(SLP_MCAST_ADDRESS);
|
|
sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_MULTICAST);
|
|
}
|
|
else
|
|
{
|
|
peeraddr.s_addr = htonl(SLP_BCAST_ADDRESS);
|
|
sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST);
|
|
}
|
|
|
|
if ( sock )
|
|
{
|
|
/*----------------------------------------------------------*/
|
|
/* Make the srvrqst and add the socket to the outgoing list */
|
|
/*----------------------------------------------------------*/
|
|
MakeActiveDiscoveryRqst(1,&(sock->sendbuf));
|
|
SLPDOutgoingDatagramWrite(sock);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
G_SlpdProperty.nextActiveDiscovery = G_SlpdProperty.nextActiveDiscovery - seconds;
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDAPassiveDAAdvert(int seconds, int dadead)
|
|
/* Send passive daadvert messages if properly configured and running as */
|
|
/* a DA */
|
|
/* */
|
|
/* seconds (IN) number seconds that elapsed since the last call to this */
|
|
/* function */
|
|
/* */
|
|
/* dadead (IN) nonzero if the DA is dead and a bootstamp of 0 should be */
|
|
/* sent */
|
|
/* */
|
|
/* Returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
struct in_addr peeraddr;
|
|
SLPDSocket* sock;
|
|
#ifdef ENABLE_SLPv1
|
|
SLPDSocket* v1sock;
|
|
#endif
|
|
|
|
|
|
/* SAs don't send passive DAAdverts */
|
|
if ( G_SlpdProperty.isDA == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Check to see if we should perform passive DA detection */
|
|
if ( G_SlpdProperty.passiveDADetection == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( G_SlpdProperty.nextPassiveDAAdvert <= 0 || dadead )
|
|
{
|
|
G_SlpdProperty.nextPassiveDAAdvert = G_SlpdProperty.DAHeartBeat;
|
|
|
|
/*--------------------------------------------------*/
|
|
/* Create new DATAGRAM socket with appropriate peer */
|
|
/*--------------------------------------------------*/
|
|
if ( G_SlpdProperty.isBroadcastOnly == 0 )
|
|
{
|
|
peeraddr.s_addr = htonl(SLP_MCAST_ADDRESS);
|
|
sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_MULTICAST);
|
|
|
|
#ifdef ENABLE_SLPv1
|
|
if ( !dadead )
|
|
{
|
|
peeraddr.s_addr = htonl(SLPv1_DA_MCAST_ADDRESS);
|
|
v1sock = SLPDSocketCreateDatagram(&peeraddr,
|
|
DATAGRAM_MULTICAST);
|
|
}
|
|
else
|
|
{
|
|
v1sock = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
peeraddr.s_addr = htonl(SLP_BCAST_ADDRESS);
|
|
sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST);
|
|
|
|
#ifdef ENABLE_SLPv1
|
|
if ( !dadead )
|
|
{
|
|
v1sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST);
|
|
}
|
|
else
|
|
{
|
|
v1sock = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Generate the DAAdvert and link it to the write list */
|
|
if ( sock )
|
|
{
|
|
if (SLPDKnownDAGenerateMyDAAdvert(0,dadead,0,&(sock->sendbuf)) == 0)
|
|
{
|
|
SLPDOutgoingDatagramWrite(sock);
|
|
}
|
|
else
|
|
{
|
|
SLPDSocketFree(sock);
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_SLPv1
|
|
if ( v1sock )
|
|
{
|
|
/* SLPv1 does not support shutdown messages */
|
|
|
|
/* Generate the DAAdvert and write it */
|
|
if (SLPDKnownDAGenerateMyV1DAAdvert(0,
|
|
SLP_CHAR_UTF8,
|
|
SLPXidGenerate(),
|
|
&(v1sock->sendbuf)) == 0)
|
|
{
|
|
SLPDOutgoingDatagramWrite(v1sock);
|
|
}
|
|
else
|
|
{
|
|
SLPDSocketFree(v1sock);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
G_SlpdProperty.nextPassiveDAAdvert = G_SlpdProperty.nextPassiveDAAdvert - seconds;
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDAImmortalRefresh(int seconds)
|
|
/* Refresh all SLP_LIFETIME_MAXIMUM services */
|
|
/* */
|
|
/* seconds (IN) time in seconds since last call */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
SLPDAAdvert* entrydaadvert;
|
|
|
|
G_KnownDATimeSinceLastRefresh += seconds;
|
|
|
|
if ( G_KnownDATimeSinceLastRefresh >= SLP_LIFETIME_MAXIMUM - seconds )
|
|
{
|
|
/* Refresh all SLP_LIFETIME_MAXIMUM registrations */
|
|
dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
|
|
if(dh)
|
|
{
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* Check to see if there is already an identical entry */
|
|
/*-----------------------------------------------------*/
|
|
while ( 1 )
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if ( entry == NULL ) break;
|
|
|
|
/* entrydaadvert is the DAAdvert message from the database */
|
|
entrydaadvert = &(entry->msg->body.daadvert);
|
|
|
|
/* Assume DAs are identical if their URLs match */
|
|
if ( SLPCompareString(entrydaadvert->urllen,
|
|
entrydaadvert->url,
|
|
G_SlpdProperty.myUrlLen,
|
|
G_SlpdProperty.myUrl) )
|
|
{
|
|
SLPDKnownDARegisterAll(entry->msg,1);
|
|
}
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
G_KnownDATimeSinceLastRefresh = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDADeRegisterWithAllDas(SLPMessage msg, SLPBuffer buf)
|
|
/* Deregister the registration described by the specified message */
|
|
/* */
|
|
/* msg (IN) A message descriptor for a SrvReg or SrvDereg message to */
|
|
/* deregister */
|
|
/* */
|
|
/* buf (IN) Message buffer associated with msg */
|
|
/* */
|
|
/* Returns: None */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPBuffer sendbuf;
|
|
|
|
if(msg->header.functionid == SLP_FUNCT_SRVREG)
|
|
{
|
|
if(MakeSrvderegFromSrvReg(msg,buf, &sendbuf) == 0)
|
|
{
|
|
SLPDKnownDAEcho(msg,sendbuf);
|
|
SLPBufferFree(sendbuf);
|
|
}
|
|
}
|
|
else if (msg->header.functionid == SLP_FUNCT_SRVDEREG)
|
|
{
|
|
/* Simply echo the message through as is */
|
|
SLPDKnownDAEcho(msg,buf);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPDKnownDARegisterWithAllDas(SLPMessage msg, SLPBuffer buf)
|
|
/* Register the registration described by the specified message with all */
|
|
/* known DAs */
|
|
/* */
|
|
/* msg (IN) A message descriptor for a SrvReg or SrvDereg message to */
|
|
/* register */
|
|
/* */
|
|
/* buf (IN) Message buffer associated with msg */
|
|
/* */
|
|
/* Returns: None */
|
|
/*=========================================================================*/
|
|
{
|
|
if (msg->header.functionid == SLP_FUNCT_SRVREG)
|
|
{
|
|
/* Simply echo the message through as is */
|
|
SLPDKnownDAEcho(msg,buf);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/*=========================================================================*/
|
|
void SLPDKnownDADump()
|
|
/*=========================================================================*/
|
|
{
|
|
SLPMessage msg;
|
|
SLPBuffer buf;
|
|
void* eh;
|
|
|
|
eh = SLPDKnownDAEnumStart();
|
|
if ( eh )
|
|
{
|
|
SLPDLog("========================================================================\n");
|
|
SLPDLog("Dumping KnownDAs \n");
|
|
SLPDLog("========================================================================\n");
|
|
while ( SLPDKnownDAEnum(eh, &msg, &buf) )
|
|
{
|
|
SLPDLogMessageInternals(msg);
|
|
SLPDLog("\n");
|
|
}
|
|
|
|
SLPDKnownDAEnumEnd(eh);
|
|
}
|
|
}
|
|
#endif
|
|
|