#include <stdio.h>
#include <string.h>
#include <unistd.h> // for _POSIX_THREADS
#include <pthread.h> // for pthread_*_t
#include "mslp_sd.h"
#include "slp.h"
#include "mslp.h"
#include "mslp_dat.h"
#include "mslplib.h"
static void remove_dae( DATable *pdat, struct sockaddr_in sin);
EXPORT void dat_delete( DATable *pdat ) {
if (pdat) {
int i;
for (i = 0; i < pdat->iSize; i++) {
SLPFree(pdat->pDAE[i].pcScopeList);
}
SLPFree(pdat->pDAE);
SLPFree(pdat);
}
}
EXPORT DATable * dat_init()
{
DATable *pdat = (DATable*) safe_malloc(sizeof(DATable),0,0);
pdat->iSize = 0;
pdat->iMax = DATINCR;
pdat->pDAE = (DAEntry*) safe_malloc(sizeof(DAEntry) * DATINCR,0,0);
pdat->initialized = SLP_FALSE;
LockGlobalDATable();
#ifdef EXTRA_MSGS
pdat->pcSASList = NULL;
pdat->iSASListSz = 0;
#endif
pdat->initialized = SLP_TRUE;
UnlockGlobalDATable();
return pdat;
}
EXPORT int dat_daadvert_in(DATable *ignore, struct sockaddr_in sin,
const char *pcScopeList, long lBootTime)
{
DATable* pdat = GetGlobalDATable();
int retval = 0;
if (!pdat || !pcScopeList ) return SLP_PARAMETER_BAD;
if (SLPGetProperty("com.sun.slp.noDA") && !SDstrcasecmp(SLPGetProperty("com.sun.slp.noDA"),"true"))
return 0;
if (lBootTime == 0)
remove_dae(pdat,sin);
else
{
int i,found = 0;
LockGlobalDATable();
for (i = 0; i < pdat->iSize; i++)
{
if (pdat->pDAE[i].sin.sin_addr.s_addr == sin.sin_addr.s_addr)
{
found = 1;
if (pdat->pDAE[i].lBootTime < lBootTime || strcmp(pcScopeList, pdat->pDAE[i].pcScopeList) != 0)
{
pdat->pDAE[i].lBootTime = lBootTime;
free(pdat->pDAE[i].pcScopeList);
pdat->pDAE[i].pcScopeList = list_pack(pcScopeList);
pdat->pDAE[i].iStrikes = 0; retval = 1;
if ( pdat->pDAE[i].iDAIsScopeSponser )
{
}
#ifdef ENABLE_SLP_LOGGING
SLP_LOG (SLP_LOG_MSG, "Updating DA [%s], in list with scopelist: %s", inet_ntoa(sin.sin_addr), pcScopeList );
#endif
}
break;
}
}
if (found == 0)
{
if ((pdat->iSize+1) == pdat->iMax)
{
DAEntry *pdae = (DAEntry*)
safe_malloc((pdat->iMax+DATINCR)*sizeof(DAEntry),(char*)pdat->pDAE,
pdat->iMax*sizeof(DAEntry));
free(pdat->pDAE);
pdat->pDAE = pdae;
pdat->iMax += DATINCR;
}
pdat->pDAE[pdat->iSize].sin.sin_addr.s_addr = sin.sin_addr.s_addr;
pdat->pDAE[pdat->iSize].sin.sin_family = AF_INET;
pdat->pDAE[pdat->iSize].sin.sin_port = htons(SLP_PORT);
pdat->pDAE[pdat->iSize].pcScopeList = list_pack(pcScopeList);
pdat->pDAE[pdat->iSize].lBootTime = lBootTime;
pdat->pDAE[pdat->iSize].iStrikes = 0;
pdat->pDAE[pdat->iSize].iDAIsScopeSponser = false;
pdat->iSize++;
retval = 1;
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "Adding DA [%s], to list with scopelist: %s", inet_ntoa(sin.sin_addr), pcScopeList );
#endif
}
UnlockGlobalDATable();
}
return retval;
}
#ifdef EXTRA_MSGS
EXPORT void dat_saadvert_in(DATable *ignore,
const char *pcScopeList,
const char *pcAttrlist) {
DATable* pdat = GetGlobalDATable();
if (!pcScopeList) return;
if (pdat->pcSASList == NULL) {
char *pcPacked = list_pack(pcScopeList);
int i = strlen(pcPacked);
pdat->pcSASList = safe_malloc(i+LISTINCR,pcPacked,i);
pdat->iSASListSz = LISTINCR+i;
free(pcPacked);
} else {
list_merge(pcScopeList, &(pdat->pcSASList), &(pdat->iSASListSz), CHECK);
}
}
#endif
EXPORT SLPInternalError dat_get_da(const DATable *ignore, const char *pcScopeList,
struct sockaddr_in *psin)
{
int i, found = 0;
DATable* pdat = GetGlobalDATable(); SLPInternalError error = SLP_OK;
if (!pdat || !pcScopeList || !psin) return SLP_PARAMETER_BAD;
LockGlobalDATable();
psin->sin_addr.s_addr = 0L;
if (SLPGetProperty("com.sun.slp.noDA") && !SDstrcasecmp(SLPGetProperty("com.sun.slp.noDA"),"true"))
{
error = SLP_OK;
}
else
{
for (i = 0; i < pdat->iSize; i++)
{
if (list_intersection(pcScopeList,pdat->pDAE[i].pcScopeList))
{
*psin = pdat->pDAE[i].sin;
found = 1;
break;
}
}
if ( pdat->iSize && !found )
{
error = SLP_SCOPE_NOT_SUPPORTED;
}
}
UnlockGlobalDATable();
return error;
}
#define kNumberOfStrikesAllowed 3
EXPORT void dat_boot_off_struck_out_das( void )
{
DATable* pdat = GetGlobalDATable();
int i;
#ifdef ENABLE_SLP_LOGGING
int initialSize = pdat->iSize;
#endif
LockGlobalDATable();
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_boot_off_struck_out_das called, %d DAs in list.",initialSize);
#endif
for (i = 0; i < pdat->iSize; i++)
{
if ( pdat->pDAE[i].iStrikes > kNumberOfStrikesAllowed )
{
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_boot_off_struck_out_das called, removing DA [%s] from list as it has too many strikes against it.",inet_ntoa(pdat->pDAE[i].sin.sin_addr));
#endif
remove_dae(pdat,pdat->pDAE[i].sin);
break;
}
}
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_boot_off_struck_out_das struck out, %d DAs.",initialSize-(pdat->iSize));
#endif
UnlockGlobalDATable();
}
EXPORT SLPInternalError dat_strike_da(DATable *ignore, struct sockaddr_in sin)
{
int i;
DATable* pdat = GetGlobalDATable();
if (!pdat)
{
#ifdef ENABLE_SLP_LOGGING
SLP_LOG(SLP_LOG_DEBUG, "dat_strike_da called but we have no global DATable" );
#endif
return SLP_PARAMETER_BAD;
}
LockGlobalDATable();
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_strike_da called, %d DAs in list.",pdat->iSize );
#endif
for (i = 0; i < pdat->iSize; i++)
{
if (pdat->pDAE[i].sin.sin_addr.s_addr == sin.sin_addr.s_addr)
{
if (!OnlyUsePreConfiguredDAs() && pdat->pDAE[i].iStrikes++ > kNumberOfStrikesAllowed)
{
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_strike_da called, removing DA [%s] from list as it has too many strikes against it.",inet_ntoa(sin.sin_addr) );
#endif
remove_dae(pdat,sin);
break;
}
else
{
DAEntry daeTemp = pdat->pDAE[i];
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_strike_da called, adding a strike to DA [%s] (%d strikes).",inet_ntoa(sin.sin_addr), pdat->pDAE[i].iStrikes );
#endif
if (i < (pdat->iSize-1))
{
memmove(&(pdat->pDAE[i]),&(pdat->pDAE[i+1]),
sizeof(DAEntry) * (pdat->iSize - i));
pdat->pDAE[pdat->iSize-1] = daeTemp;
break;
}
}
}
}
UnlockGlobalDATable();
return SLP_OK;
}
EXPORT SLPInternalError dat_update_da_scope_sponser_info(struct sockaddr_in sin, bool isScopeSponser)
{
int i;
DATable* pdat = GetGlobalDATable();
if (!pdat)
{
#ifdef ENABLE_SLP_LOGGING
SLP_LOG(SLP_LOG_DEBUG, "dat_update_da_scope_sponser_info called but we have no global DATable" );
#endif
return SLP_PARAMETER_BAD;
}
LockGlobalDATable();
#ifdef ENABLE_SLP_LOGGING
SLP_LOG( SLP_LOG_MSG, "dat_update_da_scope_sponser_info called, %d DAs in list.",pdat->iSize );
#endif
for (i = 0; i < pdat->iSize; i++)
{
if (pdat->pDAE[i].sin.sin_addr.s_addr == sin.sin_addr.s_addr)
{
pdat->pDAE[i].iDAIsScopeSponser = isScopeSponser;
}
}
UnlockGlobalDATable();
return SLP_OK;
}
EXPORT SLPInternalError dat_get_scopes(SLPHandle slph,
const char *pcTypeHint,
const DATable *ignore,
char **ppcScopes)
{
DATable* pdat = GetGlobalDATable();
char *pcList, *pcScan;
int iListLen = LISTINCR;
int i;
LockGlobalDATable();
*ppcScopes = NULL;
if (!pdat || !ppcScopes)
return SLP_PARAMETER_BAD;
if (SLPGetProperty("net.slp.useScopes") != NULL)
{
*ppcScopes = strdup(SLPGetProperty("net.slp.useScopes"));
return SLP_OK;
}
#ifdef EXTRA_MSGS
if (slph != NULL && pdat->iSize == 0)
{
active_sa_discovery(slph,pcTypeHint);
if (pdat->pcSASList)
{
int iLen = strlen(pdat->pcSASList);
*ppcScopes = safe_malloc(iLen+1,pdat->pcSASList,iLen);
}
return SLP_OK;
}
#endif
if (pdat->iSize == 0)
return SLP_OK;
iListLen += strlen(pdat->pDAE[0].pcScopeList);
pcList = safe_malloc(iListLen, (char*)pdat->pDAE[0].pcScopeList,
iListLen-LISTINCR);
if( !pcList ) return SLP_INTERNAL_SYSTEM_ERROR;
if (pdat->iSize > 1)
{
for (i = 1; i < pdat->iSize; i++)
{
pcScan = list_pack(pdat->pDAE[i].pcScopeList);
list_merge(pcScan,&pcList,&iListLen,CHECK);
free(pcScan);
}
}
*ppcScopes = pcList;
UnlockGlobalDATable();
return SLP_OK;
}
static void remove_dae(DATable *pdat, struct sockaddr_in sin) {
int i;
for (i = 0; i < pdat->iSize; i++) {
if (pdat->pDAE[i].sin.sin_addr.s_addr == sin.sin_addr.s_addr) {
free(pdat->pDAE[i].pcScopeList);
memmove(&(pdat->pDAE[i]),&(pdat->pDAE[i+1]),
sizeof(DAEntry) * (pdat->iSize - i));
(pdat->iSize)--;
break;
}
}
}