/*=========================================================================*/ 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); } }
/*=========================================================================*/ 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); } G_KnownDAScopesLen = 0; if(G_KnownDAScopes) xfree(G_KnownDAScopes); }
/*-------------------------------------------------------------------------*/ 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; }
/*=========================================================================*/ void SLPDDatabaseEnumEnd(void* eh) /* End an enumeration started by SLPDDatabaseEnumStart() */ /* */ /* Parameters: eh (IN) The enumeration handle returned by */ /* SLPDDatabaseEnumStart() */ /*=========================================================================*/ { if ( eh ) { SLPDatabaseClose((SLPDatabaseHandle)eh); } }
/*=========================================================================*/ int SLPDDatabaseReInit(const char* regfile) /* Re-initialize the database with changed registrations from a regfile. */ /* */ /* regfile (IN) the regfile to register. */ /* */ /* Returns - zero on success or non-zero on error. */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPMessage msg; SLPBuffer buf; FILE* fd; /*------------------------------------------------------------------*/ /* open the database handle and remove all the static registrations */ /* (the registrations from the /etc/slp.reg) file. */ /*------------------------------------------------------------------*/ dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) break; if ( entry->msg->body.srvreg.source == SLP_REG_SOURCE_STATIC ) { SLPDatabaseRemove(dh,entry); } } SLPDatabaseClose(dh); } /*--------------------------------------*/ /* Read static registration file if any */ /*--------------------------------------*/ if ( regfile ) { fd = fopen(regfile,"rb"); if ( fd ) { while ( SLPDRegFileReadSrvReg(fd, &msg, &buf) == 0 ) { SLPDDatabaseReg(msg, buf); } fclose(fd); } } return 0; }
/*-------------------------------------------------------------------------*/ 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 SLPDDatabaseIsEmpty() /* Returns an boolean value indicating whether the database is empty */ /*=========================================================================*/ { int result = 1; SLPDatabaseHandle dh; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); { result = SLPDatabaseCount(dh) == 0; SLPDatabaseClose(dh); } return result; }
/*=========================================================================*/ void SLPDDatabaseSrvTypeRqstEnd(SLPDDatabaseSrvTypeRqstResult* result) /* Release resources used to find service types in the database */ /* */ /* result (IN) pointer result structure previously passed to */ /* SLPDDatabaseSrvTypeRqstStart */ /* */ /* Returns - None */ /*=========================================================================*/ { if ( result ) { SLPDatabaseClose((SLPDatabaseHandle)result->reserved); xfree(result); } }
/*=========================================================================*/ int KnownDAGetScopes(int* scopelistlen, char** scopelist) /* 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; time_t curtime; SLPDatabaseHandle dh; SLPDatabaseEntry* entry; /* Refresh the cache if necessary */ curtime = time(&curtime); if(G_KnownDALastCacheRefresh == 0 || curtime - G_KnownDALastCacheRefresh > MINIMUM_DISCOVERY_INTERVAL) { G_KnownDALastCacheRefresh = curtime; /* discover DAs */ if(KnownDADiscoverFromIPC() == 0) { KnownDADiscoverFromDHCP(); KnownDADiscoverFromProperties(); KnownDADiscoverFromMulticast(0,""); } } /* 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 SLPDDatabaseAge(int seconds, int ageall) /* Ages the database entries and clears new and deleted entry lists */ /* */ /* seconds (IN) the number of seconds to age each entry by */ /* */ /* ageall (IN) age even entries with SLP_LIFETIME_MAXIMUM */ /* */ /* Returns - None */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* srvreg; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) break; /* srvreg is the SrvReg message from the database */ srvreg = &(entry->msg->body.srvreg); if ( srvreg->urlentry.lifetime == SLP_LIFETIME_MAXIMUM ) { if ( srvreg->source == SLP_REG_SOURCE_LOCAL ) { /* entries that were made from local registrations */ /* that have a lifetime of SLP_LIFETIME_MAXIMUM must */ /* NEVER be aged */ continue; } if ( ageall == 0 ) { /* Don't age any services that have a lifetime of */ /* SLP_LIFETIME_MAXIMUM unless explicitly told to */ continue; } } /* Age entries by seconds */ srvreg->urlentry.lifetime -= seconds; /* Age local entries to death when registering pid disappears */ if(srvreg->source == SLP_REG_SOURCE_LOCAL && srvreg->pid) { /* Send benign signal to process (don't worry, chances are * that we'll get an EPERM since we've droped root * permissions) */ if(SLPPidExists(srvreg->pid)) { srvreg->urlentry.lifetime = 0; SLPDKnownDADeRegisterWithAllDas(entry->msg,entry->buf); } } /* Remove entries that have timed out */ if ( srvreg->urlentry.lifetime <= 0 ) { SLPDatabaseRemove(dh,entry); SLPDLogRegistration("Timeout",entry); } } SLPDatabaseClose(dh); } }
/*=========================================================================*/ int SLPDDatabaseSrvTypeRqstStart(SLPMessage msg, SLPDDatabaseSrvTypeRqstResult** result) /* Find service types in the database */ /* */ /* msg (IN) the SrvTypRqst to find. */ /* */ /* result (OUT) pointer result structure */ /* */ /* Returns - Zero on success. Non-zero on failure */ /* */ /* Note: Caller must pass *result to SLPDDatabaseSrvtypeRqstEnd() to */ /* free */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvTypeRqst* srvtyperqst; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /* srvtyperqst is the SrvTypeRqst being made */ srvtyperqst = &(msg->body.srvtyperqst); while ( 1 ) { /*-----------------------------------------------------------------*/ /* Allocate result with generous srvtypelist of url entry pointers */ /*-----------------------------------------------------------------*/ *result = (SLPDDatabaseSrvTypeRqstResult*) xrealloc(*result, sizeof(SLPDDatabaseSrvTypeRqstResult) + G_SlpdDatabase.srvtypelistlen); if ( *result == NULL ) { /* out of memory */ SLPDatabaseClose(dh); return SLP_ERROR_INTERNAL_ERROR; } (*result)->srvtypelist = (char*)((*result) + 1); (*result)->srvtypelistlen = 0; (*result)->reserved = dh; /*-------------------------------------------------*/ /* Rewind enumeration in case we had to reallocate */ /*-------------------------------------------------*/ SLPDatabaseRewind(dh); while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) { /* This is the only successful way out */ return 0; } /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); if ( SLPCompareNamingAuth(entryreg->srvtypelen, entryreg->srvtype, srvtyperqst->namingauthlen, srvtyperqst->namingauth) == 0 && SLPIntersectStringList(srvtyperqst->scopelistlen, srvtyperqst->scopelist, entryreg->scopelistlen, entryreg->scopelist) && SLPContainsStringList((*result)->srvtypelistlen, (*result)->srvtypelist, entryreg->srvtypelen, entryreg->srvtype) == 0 ) { /* Check to see if we allocated a big enough srvtypelist */ if ( (*result)->srvtypelistlen + entryreg->srvtypelen > G_SlpdDatabase.srvtypelistlen ) { /* Oops we did not allocate a big enough result */ G_SlpdDatabase.srvtypelistlen *= 2; break; } /* Append a comma if needed */ if ( (*result)->srvtypelistlen ) { (*result)->srvtypelist[(*result)->srvtypelistlen] = ','; (*result)->srvtypelistlen += 1; } /* Append the service type */ memcpy(((*result)->srvtypelist) + (*result)->srvtypelistlen, entryreg->srvtype, entryreg->srvtypelen); (*result)->srvtypelistlen += entryreg->srvtypelen; } } } SLPDatabaseClose(dh); } return 0; }
/*=========================================================================*/ int SLPDDatabaseSrvRqstStart(SLPMessage msg, SLPDDatabaseSrvRqstResult** result) /* Find services in the database */ /* */ /* msg (IN) the SrvRqst to find. */ /* */ /* result (OUT) pointer result structure */ /* */ /* Returns - Zero on success. Non-zero on failure */ /* */ /* Note: Caller must pass *result to SLPDDatabaseSrvRqstEnd() to free */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvRqst* srvrqst; #ifdef ENABLE_SLPv2_SECURITY int i; #endif /* start with the result set to NULL just to be safe */ *result = NULL; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /* srvrqst is the SrvRqst being made */ srvrqst = &(msg->body.srvrqst); while ( 1 ) { /*-----------------------------------------------------------*/ /* Allocate result with generous array of url entry pointers */ /*-----------------------------------------------------------*/ *result = (SLPDDatabaseSrvRqstResult*) xrealloc(*result, sizeof(SLPDDatabaseSrvRqstResult) + (sizeof(SLPUrlEntry*) * G_SlpdDatabase.urlcount)); if ( *result == NULL ) { /* out of memory */ SLPDatabaseClose(dh); return SLP_ERROR_INTERNAL_ERROR; } (*result)->urlarray = (SLPUrlEntry**)((*result) + 1); (*result)->urlcount = 0; (*result)->reserved = dh; /*-------------------------------------------------*/ /* Rewind enumeration in case we had to reallocate */ /*-------------------------------------------------*/ SLPDatabaseRewind(dh); /*-----------------------------------------*/ /* Check to see if there is matching entry */ /*-----------------------------------------*/ while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) { /* This is the only successful way out */ return 0; } /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); /* check the service type */ if ( SLPCompareSrvType(srvrqst->srvtypelen, srvrqst->srvtype, entryreg->srvtypelen, entryreg->srvtype) == 0 && SLPIntersectStringList(entryreg->scopelistlen, entryreg->scopelist, srvrqst->scopelistlen, srvrqst->scopelist) > 0 ) { #ifdef ENABLE_PREDICATES if ( SLPDPredicateTest(msg->header.version, entryreg->attrlistlen, entryreg->attrlist, srvrqst->predicatelen, srvrqst->predicate) ) #endif { #ifdef ENABLE_SLPv2_SECURITY if ( srvrqst->spistrlen ) { for ( i=0; i< entryreg->urlentry.authcount;i++ ) { if ( SLPCompareString(srvrqst->spistrlen, srvrqst->spistr, entryreg->urlentry.autharray[i].spistrlen, entryreg->urlentry.autharray[i].spistr) == 0 ) { break; } } if ( i == entryreg->urlentry.authcount ) { continue; } } #endif if ( (*result)->urlcount + 1 > G_SlpdDatabase.urlcount ) { /* Oops we did not allocate a big enough result */ G_SlpdDatabase.urlcount *= 2; break; } (*result)->urlarray[(*result)->urlcount] = &(entryreg->urlentry); (*result)->urlcount ++; } } } } } return 0; }
/*=========================================================================*/ int SLPDDatabaseDeReg(SLPMessage msg) /* Remove a service registration from the database */ /* */ /* msg - (IN) message interpreting an SrvDereg message */ /* */ /* Returns - Zero on success. Non-zero on failure */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvDeReg* dereg; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /* dereg is the SrvDereg being deregistered */ dereg = &(msg->body.srvdereg); /*---------------------------------------------*/ /* Check to see if there is an identical entry */ /*---------------------------------------------*/ while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) break; /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); if ( SLPCompareString(entryreg->urlentry.urllen, entryreg->urlentry.url, dereg->urlentry.urllen, dereg->urlentry.url) == 0 ) { if ( SLPIntersectStringList(entryreg->scopelistlen, entryreg->scopelist, dereg->scopelistlen, dereg->scopelist) > 0 ) { /* Check to ensure the source addr is the same as */ /* the original */ if ( G_SlpdProperty.checkSourceAddr && memcmp(&(entry->msg->peer.sin_addr), &(msg->peer.sin_addr), sizeof(struct in_addr)) ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #ifdef ENABLE_SLPv2_SECURITY if ( entryreg->urlentry.authcount && entryreg->urlentry.authcount != dereg->urlentry.authcount ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #endif /* remove the registration from the database */ SLPDatabaseRemove(dh,entry); SLPDLogRegistration("Deregistration",entry); break; } } } SLPDatabaseClose(dh); if ( entry==NULL ) { return SLP_ERROR_INVALID_REGISTRATION; } } return 0; }
/*=========================================================================*/ int SLPDDatabaseReg(SLPMessage msg, SLPBuffer buf) /* Add a service registration to the database */ /* */ /* msg (IN) SLPMessage of a SrvReg message as returned by */ /* SLPMessageParse() */ /* */ /* buf (IN) Otherwise unreferenced buffer interpreted by the msg */ /* structure */ /* */ /* Returns - Zero on success. Nonzero on error */ /* */ /* NOTE: All registrations are treated as fresh */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvReg* reg; int result; /* reg is the SrvReg message being registered */ reg = &(msg->body.srvreg); /* check service-url syntax */ if ( SLPCheckServiceUrlSyntax(reg->urlentry.url, reg->urlentry.urllen) ) { return SLP_ERROR_INVALID_REGISTRATION; } /* check attr-list syntax */ if ( reg->attrlistlen && SLPCheckAttributeListSyntax(reg->attrlist,reg->attrlistlen) ) { return SLP_ERROR_INVALID_REGISTRATION; } dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /*-----------------------------------------------------*/ /* Check to see if there is already an identical entry */ /*-----------------------------------------------------*/ while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) break; /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); if ( SLPCompareString(entryreg->urlentry.urllen, entryreg->urlentry.url, reg->urlentry.urllen, reg->urlentry.url) == 0 ) { if ( SLPIntersectStringList(entryreg->scopelistlen, entryreg->scopelist, reg->scopelistlen, reg->scopelist) > 0 ) { /* Check to ensure the source addr is the same */ /* as the original */ if ( G_SlpdProperty.checkSourceAddr && memcmp(&(entry->msg->peer.sin_addr), &(msg->peer.sin_addr), sizeof(struct in_addr)) ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #ifdef ENABLE_SLPv2_SECURITY if ( entryreg->urlentry.authcount && entryreg->urlentry.authcount != reg->urlentry.authcount ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #endif /* Remove the identical entry */ SLPDatabaseRemove(dh,entry); break; } } } /*------------------------------------*/ /* Add the new srvreg to the database */ /*------------------------------------*/ entry = SLPDatabaseEntryCreate(msg,buf); if ( entry ) { /* set the source (allows for quicker aging ) */ if ( msg->body.srvreg.source == SLP_REG_SOURCE_UNKNOWN ) { if ( ISLOCAL(msg->peer.sin_addr) ) { msg->body.srvreg.source = SLP_REG_SOURCE_LOCAL; } else { msg->body.srvreg.source = SLP_REG_SOURCE_REMOTE; } } /* add to database */ SLPDatabaseAdd(dh, entry); SLPDLogRegistration("Registration",entry); /* SUCCESS! */ result = 0; } else { result = SLP_ERROR_INTERNAL_ERROR; } SLPDatabaseClose(dh); } else { result = SLP_ERROR_INTERNAL_ERROR; } return result; }