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.
962 lines
34 KiB
962 lines
34 KiB
/***************************************************************************/
|
|
/* */
|
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
|
/* Protocol */
|
|
/* */
|
|
/* File: libslp_knownda.c */
|
|
/* */
|
|
/* Abstract: Internal implementation for generating unique XIDs. */
|
|
/* Provides functions that are supposed to generate 16-bit */
|
|
/* values that won't be generated for a long time in this */
|
|
/* process and hopefully won't be generated by other process */
|
|
/* for a long time. */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* 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 "slp.h"
|
|
#include "libslp.h"
|
|
#include "slp_dhcp.h"
|
|
|
|
#ifndef _WIN32
|
|
#define closesocket close
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
/*=========================================================================*/
|
|
SLPDatabase G_KnownDACache ={0,0,0};
|
|
/* The cache DAAdvert messages from known DAs. */
|
|
/*=========================================================================*/
|
|
|
|
/*=========================================================================*/
|
|
int G_KnownDAScopesLen = 0;
|
|
char* G_KnownDAScopes = 0;
|
|
/* Cached known scope list */
|
|
/*=========================================================================*/
|
|
|
|
|
|
/*=========================================================================*/
|
|
time_t G_KnownDALastCacheRefresh = 0;
|
|
/* The time of the last Multicast for known DAs */
|
|
/*=========================================================================*/
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
SLPBoolean KnownDAListFind(int scopelistlen,
|
|
const char* scopelist,
|
|
int spistrlen,
|
|
const char* spistr,
|
|
struct in_addr* daaddr)
|
|
/* Returns: non-zero on success, zero if DA can not be found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
int result = SLP_FALSE;
|
|
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
/*----------------------------------------*/
|
|
/* Check to see if there a matching entry */
|
|
/*----------------------------------------*/
|
|
while(1)
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if(entry == NULL) break;
|
|
|
|
/* Check scopes */
|
|
if(SLPSubsetStringList(entry->msg->body.daadvert.scopelistlen,
|
|
entry->msg->body.daadvert.scopelist,
|
|
scopelistlen,
|
|
scopelist))
|
|
{
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if(SLPCompareString(entry->msg->body.daadvert.spilistlen,
|
|
entry->msg->body.daadvert.spilist,
|
|
spistrlen,
|
|
spistr) == 0)
|
|
#endif
|
|
{
|
|
|
|
memcpy(daaddr,
|
|
&(entry->msg->peer.sin_addr),
|
|
sizeof(struct in_addr));
|
|
|
|
result = SLP_TRUE;
|
|
}
|
|
}
|
|
}
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int KnownDAAdd(SLPMessage msg, SLPBuffer buf)
|
|
/* Add an entry to the KnownDA cache */
|
|
/* */
|
|
/* Returns: zero on success, non-zero on error */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
SLPDAAdvert* entrydaadvert;
|
|
SLPDAAdvert* daadvert;
|
|
int result;
|
|
|
|
result = 0;
|
|
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
/* daadvert is the DAAdvert message being added */
|
|
daadvert = &(msg->body.daadvert);
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* 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)
|
|
{
|
|
SLPDatabaseRemove(dh,entry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Create and link in a new entry */
|
|
entry = SLPDatabaseEntryCreate(msg,buf);
|
|
if(entry)
|
|
{
|
|
SLPDatabaseAdd(dh, entry);
|
|
}
|
|
else
|
|
{
|
|
result = SLP_MEMORY_ALLOC_FAILED;
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
SLPBoolean KnownDADiscoveryCallback(SLPError errorcode,
|
|
struct sockaddr_in* peerinfo,
|
|
SLPBuffer rplybuf,
|
|
void* cookie)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPMessage replymsg;
|
|
SLPBuffer dupbuf;
|
|
struct hostent* he;
|
|
SLPSrvURL* srvurl;
|
|
int* count;
|
|
SLPBoolean result = SLP_TRUE;
|
|
|
|
count = (int*)cookie;
|
|
|
|
if(errorcode == 0)
|
|
{
|
|
dupbuf = SLPBufferDup(rplybuf);
|
|
if(dupbuf)
|
|
{
|
|
replymsg = SLPMessageAlloc();
|
|
if(replymsg)
|
|
{
|
|
if(SLPMessageParseBuffer(peerinfo,dupbuf,replymsg) == 0 &&
|
|
replymsg->header.functionid == SLP_FUNCT_DAADVERT)
|
|
{
|
|
if(replymsg->body.daadvert.errorcode == 0)
|
|
{
|
|
/* TRICKY: NULL terminate the DA url */
|
|
((char*)(replymsg->body.daadvert.url))[replymsg->body.daadvert.urllen] = 0;
|
|
if(SLPParseSrvURL(replymsg->body.daadvert.url, &srvurl) == 0)
|
|
{
|
|
replymsg->peer.sin_addr.s_addr = 0;
|
|
if(inet_aton(srvurl->s_pcHost, &(replymsg->peer.sin_addr)) == 0)
|
|
{
|
|
he = gethostbyname(srvurl->s_pcHost);
|
|
if(he)
|
|
{
|
|
/* Reset the peer to the one in the URL */
|
|
replymsg->peer.sin_addr.s_addr = *((unsigned int*)(he->h_addr_list[0]));
|
|
}
|
|
}
|
|
|
|
SLPFree(srvurl);
|
|
|
|
if(replymsg->peer.sin_addr.s_addr)
|
|
{
|
|
(*count) += 1;
|
|
|
|
KnownDAAdd(replymsg,dupbuf);
|
|
if(replymsg->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
return SLP_FALSE;
|
|
}
|
|
|
|
return SLP_TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if(replymsg->body.daadvert.errorcode == SLP_ERROR_INTERNAL_ERROR)
|
|
{
|
|
/* SLP_ERROR_INTERNAL_ERROR is a "end of stream" */
|
|
/* marker for looppack IPC */
|
|
result = SLP_FALSE;
|
|
}
|
|
}
|
|
|
|
SLPMessageFree(replymsg);
|
|
}
|
|
|
|
SLPBufferFree(dupbuf);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int KnownDADiscoveryRqstRply(int sock,
|
|
struct sockaddr_in* peeraddr,
|
|
int scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
const char* scopelist,
|
|
PSLPHandleInfo handle)
|
|
#else
|
|
const char* scopelist)
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
/* Returns: number of *new* DAEntries found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
char* buf;
|
|
char* curpos;
|
|
int bufsize;
|
|
int result = 0;
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* determine the size of the fixed portion of the SRVRQST */
|
|
/*-------------------------------------------------------------------*/
|
|
bufsize = 31; /* 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 */
|
|
bufsize += scopelistlen;
|
|
|
|
/* TODO: make sure that we don't exceed the MTU */
|
|
buf = curpos = (char*)xmalloc(bufsize);
|
|
if(buf == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
memset(buf,0,bufsize);
|
|
|
|
/*------------------------------------------------------------*/
|
|
/* Build a buffer containing the fixed portion of the SRVRQST */
|
|
/*------------------------------------------------------------*/
|
|
/* service type */
|
|
ToUINT16(curpos,23);
|
|
curpos = curpos + 2;
|
|
/* 23 is the length of SLP_DA_SERVICE_TYPE */
|
|
memcpy(curpos,SLP_DA_SERVICE_TYPE,23);
|
|
curpos += 23;
|
|
/* scope list */
|
|
ToUINT16(curpos,scopelistlen);
|
|
curpos = curpos + 2;
|
|
memcpy(curpos,scopelist,scopelistlen);
|
|
/* predicate zero length */
|
|
/* spi list zero length */
|
|
|
|
if(sock == -1)
|
|
{
|
|
|
|
#ifndef MI_NOT_SUPPORTED
|
|
NetworkMcastRqstRply(handle,
|
|
#else
|
|
NetworkMcastRqstRply("en",
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
buf,
|
|
SLP_FUNCT_DASRVRQST,
|
|
bufsize,
|
|
KnownDADiscoveryCallback,
|
|
&result);
|
|
|
|
}
|
|
else
|
|
{
|
|
NetworkRqstRply(sock,
|
|
peeraddr,
|
|
"en",
|
|
0,
|
|
buf,
|
|
SLP_FUNCT_DASRVRQST,
|
|
bufsize,
|
|
KnownDADiscoveryCallback,
|
|
&result);
|
|
}
|
|
|
|
xfree(buf);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
#ifndef MI_NOT_SUPPORTED
|
|
int KnownDADiscoverFromMulticast(int scopelistlen, const char* scopelist, PSLPHandleInfo handle)
|
|
#else
|
|
int KnownDADiscoverFromMulticast(int scopelistlen, const char* scopelist)
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
/* Locates DAs via multicast convergence */
|
|
/* */
|
|
/* Returns: number of *new* DAs found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int result = 0;
|
|
|
|
if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.activeDADetection")) &&
|
|
SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")))
|
|
{
|
|
result = KnownDADiscoveryRqstRply(-1,
|
|
NULL,
|
|
scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
scopelist,
|
|
handle);
|
|
#else
|
|
scopelist);
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
#ifndef MI_NOT_SUPPORTED
|
|
int KnownDADiscoverFromDHCP(PSLPHandleInfo handle)
|
|
#else
|
|
int KnownDADiscoverFromDHCP()
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
/* Locates DAs via DHCP */
|
|
/* */
|
|
/* Returns: number of *new* DAs found via DHCP. */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int count = 0;
|
|
int scopelistlen;
|
|
DHCPContext ctx;
|
|
unsigned char *alp;
|
|
struct timeval timeout;
|
|
struct sockaddr_in peeraddr;
|
|
unsigned char dhcpOpts[] = {TAG_SLP_SCOPE, TAG_SLP_DA};
|
|
|
|
*ctx.scopelist = 0;
|
|
ctx.addrlistlen = 0;
|
|
|
|
DHCPGetOptionInfo(dhcpOpts, sizeof(dhcpOpts), DHCPParseSLPTags, &ctx);
|
|
|
|
if(!*ctx.scopelist)
|
|
{
|
|
const char *slp = SLPGetProperty("net.slp.useScopes");
|
|
if(slp)
|
|
strcpy(ctx.scopelist, slp);
|
|
}
|
|
scopelistlen = strlen(ctx.scopelist);
|
|
|
|
memset(&peeraddr,0,sizeof(peeraddr));
|
|
peeraddr.sin_family = AF_INET;
|
|
peeraddr.sin_port = htons(SLP_RESERVED_PORT);
|
|
|
|
timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait"));
|
|
timeout.tv_usec = (timeout.tv_sec % 1000) * 1000;
|
|
timeout.tv_sec = timeout.tv_sec / 1000;
|
|
|
|
alp = ctx.addrlist;
|
|
|
|
while(ctx.addrlistlen >= 4)
|
|
{
|
|
memcpy(&peeraddr.sin_addr.s_addr, alp, 4);
|
|
if(peeraddr.sin_addr.s_addr)
|
|
{
|
|
int sockfd;
|
|
if((sockfd = SLPNetworkConnectStream(&peeraddr, &timeout)) >= 0)
|
|
{
|
|
count = KnownDADiscoveryRqstRply(sockfd,
|
|
&peeraddr,
|
|
scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
ctx.scopelist,
|
|
handle);
|
|
#else
|
|
ctx.scopelist);
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
closesocket(sockfd);
|
|
if(scopelistlen && count)
|
|
break; /* stop after the first set found */
|
|
}
|
|
}
|
|
ctx.addrlistlen -= 4;
|
|
alp += 4;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int KnownDADiscoverFromProperties(int scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
const char* scopelist,
|
|
PSLPHandleInfo handle)
|
|
#else
|
|
const char* scopelist)
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
/* Locates DAs from the property list of DA hostnames */
|
|
/* */
|
|
/* Returns: number of *new* DAs found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
char* temp;
|
|
char* tempend;
|
|
char* slider1;
|
|
char* slider2;
|
|
int sockfd;
|
|
struct hostent* he;
|
|
struct sockaddr_in peeraddr;
|
|
struct timeval timeout;
|
|
int result = 0;
|
|
|
|
memset(&peeraddr,0,sizeof(peeraddr));
|
|
peeraddr.sin_family = AF_INET;
|
|
peeraddr.sin_port = htons(SLP_RESERVED_PORT);
|
|
|
|
slider1 = slider2 = temp = xstrdup(SLPGetProperty("net.slp.DAAddresses"));
|
|
if(temp)
|
|
{
|
|
tempend = temp + strlen(temp);
|
|
while(slider1 != tempend)
|
|
{
|
|
timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait"));
|
|
timeout.tv_usec = (timeout.tv_sec % 1000) * 1000;
|
|
timeout.tv_sec = timeout.tv_sec / 1000;
|
|
|
|
while(*slider2 && *slider2 != ',') slider2++;
|
|
*slider2 = 0;
|
|
|
|
peeraddr.sin_addr.s_addr = 0;
|
|
if(inet_aton(slider1, &(peeraddr.sin_addr)) == 0)
|
|
{
|
|
he = gethostbyname(slider1);
|
|
if(he)
|
|
{
|
|
peeraddr.sin_addr.s_addr = *((unsigned int*)(he->h_addr_list[0]));
|
|
}
|
|
}
|
|
|
|
if (peeraddr.sin_addr.s_addr)
|
|
{
|
|
sockfd = SLPNetworkConnectStream(&peeraddr,&timeout);
|
|
if(sockfd >= 0)
|
|
{
|
|
result = KnownDADiscoveryRqstRply(sockfd,
|
|
&peeraddr,
|
|
scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
scopelist,
|
|
handle);
|
|
#else
|
|
scopelist);
|
|
#endif
|
|
closesocket(sockfd);
|
|
if(scopelistlen && result)
|
|
{
|
|
/* return if we found at least one DA */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
slider1 = slider2;
|
|
slider2++;
|
|
}
|
|
|
|
xfree(temp);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
#ifndef MI_NOT_SUPPORTED
|
|
int KnownDADiscoverFromIPC(PSLPHandleInfo handle)
|
|
#else
|
|
int KnownDADiscoverFromIPC()
|
|
#endif
|
|
/* Ask Slpd if it knows about a DA */
|
|
/* */
|
|
/* Returns: number of *new* DAs found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
struct sockaddr_in peeraddr;
|
|
int sockfd;
|
|
int result = 0;
|
|
|
|
sockfd = NetworkConnectToSlpd(&peeraddr);
|
|
if(sockfd >= 0)
|
|
{
|
|
#ifndef MI_NOT_SUPPORTED
|
|
result = KnownDADiscoveryRqstRply(sockfd, &peeraddr, 0, "", handle);
|
|
#else
|
|
result = KnownDADiscoveryRqstRply(sockfd, &peeraddr, 0, "");
|
|
#endif
|
|
closesocket(sockfd);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
SLPBoolean KnownDAFromCache(int scopelistlen,
|
|
const char* scopelist,
|
|
int spistrlen,
|
|
const char* spistr,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
struct in_addr* daaddr,
|
|
PSLPHandleInfo handle)
|
|
#else
|
|
struct in_addr* daaddr)
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
/* Ask Slpd if it knows about a DA */
|
|
/* */
|
|
/* Returns: non-zero on success, zero if DA can not be found */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
time_t curtime;
|
|
|
|
if(KnownDAListFind(scopelistlen,
|
|
scopelist,
|
|
spistrlen,
|
|
spistr,
|
|
daaddr) == SLP_FALSE)
|
|
{
|
|
curtime = time(&curtime);
|
|
if(G_KnownDALastCacheRefresh == 0 ||
|
|
curtime - G_KnownDALastCacheRefresh > MINIMUM_DISCOVERY_INTERVAL)
|
|
{
|
|
G_KnownDALastCacheRefresh = curtime;
|
|
|
|
/* discover DAs */
|
|
#ifndef MI_NOT_SUPPORTED
|
|
if(KnownDADiscoverFromIPC(handle) == 0)
|
|
if(KnownDADiscoverFromProperties(scopelistlen, scopelist, handle) == 0)
|
|
if(KnownDADiscoverFromDHCP(handle) == 0)
|
|
KnownDADiscoverFromMulticast(scopelistlen, scopelist, handle);
|
|
#else
|
|
if(KnownDADiscoverFromIPC() == 0)
|
|
if(KnownDADiscoverFromProperties(scopelistlen, scopelist) == 0)
|
|
if(KnownDADiscoverFromDHCP() == 0)
|
|
KnownDADiscoverFromMulticast(scopelistlen, scopelist);
|
|
#endif
|
|
}
|
|
|
|
return KnownDAListFind(scopelistlen,
|
|
scopelist,
|
|
spistrlen,
|
|
spistr,
|
|
daaddr);
|
|
}
|
|
|
|
return SLP_TRUE;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int KnownDAConnect(PSLPHandleInfo handle,
|
|
int scopelistlen,
|
|
const char* scopelist,
|
|
struct sockaddr_in* peeraddr)
|
|
/* Get a connected socket to a DA that supports the specified scope */
|
|
/* */
|
|
/* scopelistlen (IN) stringlen of the scopelist */
|
|
/* */
|
|
/* scopelist (IN) DA must support this scope */
|
|
/* */
|
|
/* peeraddr (OUT) the peer that was connected to */
|
|
/* */
|
|
/* */
|
|
/* returns: valid socket file descriptor or -1 if no DA is found */
|
|
/*=========================================================================*/
|
|
{
|
|
struct timeval timeout;
|
|
int sock = -1;
|
|
int spistrlen = 0;
|
|
char* spistr = 0;
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled")))
|
|
{
|
|
SLPSpiGetDefaultSPI(handle->hspi,
|
|
SLPSPI_KEY_TYPE_PUBLIC,
|
|
&spistrlen,
|
|
&spistr);
|
|
}
|
|
#endif
|
|
|
|
/* Set up connect timeout */
|
|
timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait"));
|
|
timeout.tv_usec = (timeout.tv_sec % 1000) * 1000;
|
|
timeout.tv_sec = timeout.tv_sec / 1000;
|
|
|
|
while(1)
|
|
{
|
|
memset(peeraddr,0,sizeof(peeraddr));
|
|
|
|
if(KnownDAFromCache(scopelistlen,
|
|
scopelist,
|
|
spistrlen,
|
|
spistr,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
&(peeraddr->sin_addr),
|
|
handle) == 0)
|
|
#else
|
|
&(peeraddr->sin_addr)) == 0)
|
|
#endif /* MI_NOT_SUPPORTED */
|
|
{
|
|
break;
|
|
}
|
|
peeraddr->sin_family = PF_INET;
|
|
peeraddr->sin_port = htons(SLP_RESERVED_PORT);
|
|
|
|
sock = SLPNetworkConnectStream(peeraddr,&timeout);
|
|
if(sock >= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
KnownDABadDA(&(peeraddr->sin_addr));
|
|
}
|
|
|
|
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
if(spistr) xfree(spistr);
|
|
#endif
|
|
|
|
return sock;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
void KnownDABadDA(struct in_addr* daaddr)
|
|
/* Mark a KnownDA as a Bad DA. */
|
|
/* */
|
|
/* daaddr (IN) address of the bad DA */
|
|
/* */
|
|
/* Returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
/*-----------------------------------*/
|
|
/* Check to find the requested entry */
|
|
/*-----------------------------------*/
|
|
while(1)
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if(entry == NULL) break;
|
|
|
|
/* Assume DAs are identical if their in_addrs match */
|
|
if(memcmp(daaddr,&(entry->msg->peer.sin_addr),sizeof(struct in_addr)) == 0)
|
|
{
|
|
SLPDatabaseRemove(dh,entry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int KnownDAGetScopes(int* scopelistlen,
|
|
#ifndef MI_NOT_SUPPORTED
|
|
char** scopelist,
|
|
PSLPHandleInfo handle)
|
|
#else
|
|
char** scopelist)
|
|
#endif
|
|
/* Gets a list of scopes from the known DA list */
|
|
/* */
|
|
/* scopelistlen (OUT) stringlen of the scopelist */
|
|
/* */
|
|
/* scopelist (OUT) NULL terminated list of scopes */
|
|
/* */
|
|
/* returns: zero on success, non-zero on failure */
|
|
/*=========================================================================*/
|
|
{
|
|
int newlen;
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
|
|
/* discover all DAs */
|
|
#ifndef MI_NOT_SUPPORTED
|
|
if(KnownDADiscoverFromIPC(handle) == 0)
|
|
#else
|
|
if(KnownDADiscoverFromIPC() == 0)
|
|
#endif
|
|
{
|
|
#ifndef MI_NOT_SUPPORTED
|
|
KnownDADiscoverFromDHCP(handle);
|
|
KnownDADiscoverFromProperties(0,"", handle);
|
|
KnownDADiscoverFromMulticast(0,"", handle);
|
|
#else
|
|
KnownDADiscoverFromDHCP();
|
|
KnownDADiscoverFromProperties(0,"");
|
|
KnownDADiscoverFromMulticast(0,"");
|
|
#endif
|
|
}
|
|
|
|
|
|
/* enumerate through all the knownda entries and generate a */
|
|
/* scopelist */
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
/*-----------------------------------*/
|
|
/* Check to find the requested entry */
|
|
/*-----------------------------------*/
|
|
while(1)
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if(entry == NULL) break;
|
|
newlen = G_KnownDAScopesLen;
|
|
while(SLPUnionStringList(G_KnownDAScopesLen,
|
|
G_KnownDAScopes,
|
|
entry->msg->body.daadvert.scopelistlen,
|
|
entry->msg->body.daadvert.scopelist,
|
|
&newlen,
|
|
G_KnownDAScopes) < 0)
|
|
{
|
|
G_KnownDAScopes = xrealloc(G_KnownDAScopes,newlen);
|
|
if(G_KnownDAScopes == 0)
|
|
{
|
|
G_KnownDAScopesLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
G_KnownDAScopesLen = newlen;
|
|
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
/* Explicitly add in the useScopes property */
|
|
newlen = G_KnownDAScopesLen;
|
|
while(SLPUnionStringList(G_KnownDAScopesLen,
|
|
G_KnownDAScopes,
|
|
strlen(SLPPropertyGet("net.slp.useScopes")),
|
|
SLPPropertyGet("net.slp.useScopes"),
|
|
&newlen,
|
|
G_KnownDAScopes) < 0)
|
|
{
|
|
G_KnownDAScopes = xrealloc(G_KnownDAScopes,newlen);
|
|
if(G_KnownDAScopes == 0)
|
|
{
|
|
G_KnownDAScopesLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
G_KnownDAScopesLen = newlen;
|
|
|
|
if(G_KnownDAScopesLen)
|
|
{
|
|
*scopelist = xmalloc(G_KnownDAScopesLen + 1);
|
|
if(*scopelist == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
memcpy(*scopelist,G_KnownDAScopes, G_KnownDAScopesLen);
|
|
(*scopelist)[G_KnownDAScopesLen] = 0;
|
|
*scopelistlen = G_KnownDAScopesLen;
|
|
}
|
|
else
|
|
{
|
|
*scopelist = xstrdup("");
|
|
if(*scopelist == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
*scopelistlen = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
void KnownDAProcessSrvRqst(PSLPHandleInfo handle)
|
|
/* Process a SrvRqst for service:directory-agent */
|
|
/* */
|
|
/* handle (IN) the handle used to make the SrvRqst */
|
|
/* */
|
|
/* returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
SLPBoolean cb_result;
|
|
char tmp;
|
|
|
|
/* discover all DAs */
|
|
#ifndef MI_NOT_SUPPORTED
|
|
if(KnownDADiscoverFromIPC(handle) == 0)
|
|
#else
|
|
if(KnownDADiscoverFromIPC() == 0)
|
|
#endif
|
|
{
|
|
#ifndef MI_NOT_SUPPORTED
|
|
KnownDADiscoverFromDHCP(handle);
|
|
KnownDADiscoverFromProperties(0,"", handle);
|
|
KnownDADiscoverFromMulticast(0,"", handle);
|
|
#else
|
|
KnownDADiscoverFromDHCP();
|
|
KnownDADiscoverFromProperties(0,"");
|
|
KnownDADiscoverFromMulticast(0,"");
|
|
#endif
|
|
}
|
|
|
|
/* Enumerate through knownDA database */
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
/* Check to see if there a matching entry */
|
|
while(1)
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
|
|
/* is there anything left? */
|
|
if(entry == NULL) break;
|
|
|
|
/* TRICKY temporary null termination of DA url */
|
|
tmp = entry->msg->body.daadvert.url[entry->msg->body.daadvert.urllen];
|
|
((char*)(entry->msg->body.daadvert.url))[entry->msg->body.daadvert.urllen] = 0;
|
|
|
|
/* Call the SrvURLCallback */
|
|
cb_result = handle->params.findsrvs.callback((SLPHandle)handle,
|
|
entry->msg->body.daadvert.url,
|
|
SLP_LIFETIME_MAXIMUM,
|
|
SLP_OK,
|
|
handle->params.findsrvs.cookie);
|
|
|
|
/* TRICKY: undo temporary null termination of DA url */
|
|
((char*)(entry->msg->body.daadvert.url))[entry->msg->body.daadvert.urllen] = tmp;
|
|
|
|
/* does the caller want more? */
|
|
if(cb_result == SLP_FALSE)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
/* Make SLP_LAST_CALL */
|
|
handle->params.findsrvs.callback((SLPHandle)handle,
|
|
NULL,
|
|
0,
|
|
SLP_LAST_CALL,
|
|
handle->params.findsrvs.cookie);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/*=========================================================================*/
|
|
void KnownDAFreeAll()
|
|
/* Frees all (cached) resources associated with known DAs */
|
|
/* */
|
|
/* returns: none */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPDatabaseHandle dh;
|
|
SLPDatabaseEntry* entry;
|
|
dh = SLPDatabaseOpen(&G_KnownDACache);
|
|
if(dh)
|
|
{
|
|
while(1)
|
|
{
|
|
entry = SLPDatabaseEnum(dh);
|
|
if(entry == NULL) break;
|
|
|
|
SLPDatabaseRemove(dh,entry);
|
|
}
|
|
|
|
SLPDatabaseClose(dh);
|
|
}
|
|
|
|
|
|
if(G_KnownDAScopes) xfree(G_KnownDAScopes);
|
|
G_KnownDAScopesLen = 0;
|
|
G_KnownDALastCacheRefresh = 0;
|
|
|
|
}
|
|
#endif
|