/* * list_intersection * * return: * 1 if there is an overlap, 0 otherwise. */ EXPORT int list_intersection(const char *pcL1, const char *pcL2) { int i1 = 0, i2 = 0; char *pcS1, *pcS2; char c; if (!pcL1 || !pcL2) { SLPLOG(SLP_LOG_ERR,"list_intersection: got NULL value as a parameter!"); return 0; } if (*pcL1 == '\0' && *pcL2 == '\0') return 1; for ( pcS1=get_next_string(",",pcL1,&i1,&c); pcS1; pcS1=get_next_string(",",pcL1,&i1,&c) ) { i2 = 0; for (pcS2=get_next_string(",",pcL2,&i2,&c); pcS2;pcS2=get_next_string(",",pcL2,&i2,&c)) { // The SLPv2 RFC2608 explicitly states in SECTION 6.4 that scope lists MUST be handled case-insensitive. int result = SDstrcasecmp(pcS1,pcS2); SLPFree(pcS2); if (result==0) { SLPFree(pcS1); return 1; } } SLPFree(pcS1); } return 0; }
/* * delete_dat * * Frees all internal state of the dat. * * Note: * The DA Table cannot be used after this! */ 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); } }
/*-------------------------------------------------------------------------*/ SLPBoolean KnownDADiscoveryCallback(SLPError errorcode, SLPMessage msg, void* cookie) /*-------------------------------------------------------------------------*/ { SLPSrvURL* srvurl; SLPDAEntry* entry; struct hostent* he; int* count = (int*)cookie; if(msg->header.functionid == SLP_FUNCT_DAADVERT) { if(msg->body.srvrply.errorcode == 0) { /* NULL terminate scopelist */ *((char*)msg->body.daadvert.scopelist + msg->body.daadvert.scopelistlen) = 0; if(SLPParseSrvURL(msg->body.daadvert.url, &srvurl) == 0) { he = gethostbyname(srvurl->s_pcHost); if(he) { entry = SLPDAEntryCreate((struct in_addr*)(he->h_addr_list[0]), msg->body.daadvert.scopelist, msg->body.daadvert.scopelistlen); ListLink((PListItem*)&G_KnownDAListHead,(PListItem)entry); *count = *count + 1; } SLPFree(srvurl); } } } return 1; }
/*-------------------------------------------------------------------------*/ void ProcessDAAdvert(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { /* TODO: enable the following when we link to libslp and */ /* have SLPParseSrvURL() */ #if(0) SLPSrvURL* srvurl; struct hostent* he; #endif /* DAAdverts should never be replied to. Set result buffer to empty*/ result->end = result->start; /* Do not look at DAAdverts if we are a DA */ if(G_SlpdProperty.isDA == 0) { /* Only process if errorcode is not set */ if(message->body.daadvert.errorcode == SLP_ERROR_OK) { /* TODO: enable the following when we link to libslp and */ /* have SLPParseSrvURL() */ #if(0) /* yes, we could just get the host addr from peer info. Looking */ /* it up is safer */ if(SLPParseSrvURL(message->body.daadvert.url, &srvurl) == 0) { he = gethostbyname(srvurl->s_pcHost); if(he) { /* Add the DA to a list of known DAs (ignore return)*/ SLPDKnownDAAdd((struct in_addr*)(he->h_addr_list[0]), message->body.daadvert.bootstamp, message->body.daadvert.scopelist, message->body.daadvert.scopelistlen); } SLPFree(srvurl); } #endif /* TODO: the following is allows for easy DA masquarading (unsafe) */ /* remove it when the above is fixed */ SLPDKnownDAAdd(&(peerinfo->peeraddr.sin_addr), message->body.daadvert.bootstamp, message->body.daadvert.scopelist, message->body.daadvert.scopelistlen); } /* If necessary log that we received a DAAdvert */ if(G_SlpdProperty.traceDATraffic) { SLPDLogDATrafficMsg("IN", peerinfo, message); } } }
/* * list_subset * * Compares two lists. All the elements in the first list must be * in the second and neither may be empty lists. * * pcSub The list which must have all elements in pcSuper * pcSuper The list which must contain all or more elements than in pcSub * * Returns: * 0 if not a subset, 1 if it is a subset. * * Side effects: * None. */ EXPORT int list_subset(const char *pcSub, const char *pcSuper) { int offset = 0; char c, *pcScope; if (!pcSub || !pcSuper || /* either are NULL */ (pcSub[0] == '\0' && pcSuper[0] != '\0')) { /* sub empty, super not */ return 0; } while((pcScope = get_next_string(",",pcSub,&offset,&c))) { if (!list_intersection(pcScope,pcSuper)) { SLPFree(pcScope); return 0; } SLPFree(pcScope); } return 1; }
void FindScopes(SLPToolCommandLine * cmdline) { SLPError result; SLPHandle hslp; char * scopes; if (SLPOpen(cmdline->lang, SLP_FALSE, &hslp) == SLP_OK) { result = SLPFindScopes(hslp, &scopes); if (result == SLP_OK) { printf("%s\n", scopes); SLPFree(scopes); } SLPClose(hslp); } }
SLPBoolean SLP::urlCallback( SLPHandle hslp, const char *srvurl, unsigned short lifetime, SLPError errcode, void *cookie) { if ((errcode == SLP_OK || errcode == SLP_LAST_CALL) && srvurl != NULL) { SLPSrvURL *url; SLPParseSrvURL(srvurl, &url); bp::list *py_srvs_ptr = static_cast<bp::list *>(cookie); py_srvs_ptr->append(SLPResult::create(url)); SLPFree(url); } return SLP_TRUE; }
/*=========================================================================*/ SLPError SLPDereg(SLPHandle hSLP, const char *srvUrl, SLPRegReport callback, void *cookie) /* */ /* See slplib.h for detailed documentation */ /*=========================================================================*/ { PSLPHandleInfo handle = 0; SLPError result = SLP_OK; SLPSrvURL* parsedurl = 0; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if( hSLP == 0 || *(unsigned long*)hSLP != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || /* url can't be empty string */ callback == 0) { return SLP_PARAMETER_BAD; } /*-----------------------------------------*/ /* cast the SLPHandle into a SLPHandleInfo */ /*-----------------------------------------*/ handle = (PSLPHandleInfo)hSLP; /*-----------------------------------------*/ /* Check to see if the handle is in use */ /*-----------------------------------------*/ if(handle->inUse == SLP_TRUE) { return SLP_HANDLE_IN_USE; } handle->inUse = SLP_TRUE; /*---------------------------------------------*/ /* Check to see if we can talk to a slpd */ /*---------------------------------------------*/ if(handle->slpdsock < 0) { /* slpd is not running locally and no DA's are configured */ handle->inUse = SLP_FALSE; return SLP_NETWORK_INIT_FAILED; } /*------------------*/ /* Parse the srvurl */ /*------------------*/ result = SLPParseSrvURL(srvUrl,&parsedurl); if(result) { if(result == SLP_PARSE_ERROR) { result = SLP_INVALID_REGISTRATION; } if(parsedurl) SLPFree(parsedurl); handle->inUse = SLP_FALSE; return result; } /*-------------------------------------------*/ /* Set the handle up to reference parameters */ /*-------------------------------------------*/ handle->params.dereg.scopelist = SLPGetProperty("net.slp.useScopes"); if(handle->params.dereg.scopelist) { handle->params.dereg.scopelistlen = strlen(handle->params.dereg.scopelist); } handle->params.dereg.urllen = strlen(srvUrl); handle->params.dereg.url = srvUrl; handle->params.dereg.callback = callback; handle->params.dereg.cookie = cookie; /*----------------------------------------------*/ /* Check to see if we should be async or sync */ /*----------------------------------------------*/ if(handle->isAsync) { /* COPY all the parameters */ handle->params.dereg.scopelist = strdup(handle->params.dereg.scopelist); handle->params.dereg.url = strdup(handle->params.dereg.url); /* make sure the strdups did not fail */ if(handle->params.dereg.scopelist && handle->params.dereg.url ) { result = ThreadCreate((ThreadStartProc)AsyncProcessSrvDeReg,handle); } else { result = SLP_MEMORY_ALLOC_FAILED; } if(result) { if(handle->params.dereg.scopelist) free((void*)handle->params.dereg.scopelist); if(handle->params.dereg.url) free((void*)handle->params.dereg.url); handle->inUse = SLP_FALSE; } } else { /* REFERENCE all the parameters */ result = ProcessSrvDeReg(handle); handle->inUse = SLP_FALSE; } if(parsedurl) SLPFree(parsedurl); return result; }
/*=========================================================================*/ SLPError SLPReg(SLPHandle hSLP, const char *srvUrl, const unsigned short lifetime, const char *srvType, const char *attrList, SLPBoolean fresh, SLPRegReport callback, void *cookie) /* */ /* See slplib.h for detailed documentation */ /*=========================================================================*/ { PSLPHandleInfo handle = 0; SLPError result = SLP_OK; SLPSrvURL* parsedurl = 0; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if(hSLP == 0 || *(unsigned int*)hSLP != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || /* srvUrl can't be empty string */ lifetime == 0 || /* lifetime can not be zero */ attrList == 0 || callback == 0) { return SLP_PARAMETER_BAD; } /*-----------------------------------------*/ /* We don't handle fresh registrations */ /*-----------------------------------------*/ if(fresh == SLP_FALSE) { return SLP_NOT_IMPLEMENTED; } /*-----------------------------------------*/ /* cast the SLPHandle into a SLPHandleInfo */ /*-----------------------------------------*/ handle = (PSLPHandleInfo)hSLP; /*-----------------------------------------*/ /* Check to see if the handle is in use */ /*-----------------------------------------*/ if(handle->inUse == SLP_TRUE) { return SLP_HANDLE_IN_USE; } handle->inUse = SLP_TRUE; /*------------------*/ /* Parse the srvurl */ /*------------------*/ result = SLPParseSrvURL(srvUrl,&parsedurl); if(result) { if(result == SLP_PARSE_ERROR) { result = SLP_INVALID_REGISTRATION; } if(parsedurl) SLPFree(parsedurl); handle->inUse = SLP_FALSE; return result; } /*-------------------------------------------*/ /* Set the handle up to reference parameters */ /*-------------------------------------------*/ handle->params.reg.fresh = fresh; handle->params.reg.lifetime = lifetime; handle->params.reg.urllen = strlen(srvUrl); handle->params.reg.url = srvUrl; handle->params.reg.srvtype = parsedurl->s_pcSrvType; handle->params.reg.srvtypelen = strlen(handle->params.reg.srvtype); handle->params.reg.scopelist = SLPGetProperty("net.slp.useScopes"); if(handle->params.reg.scopelist) { handle->params.reg.scopelistlen = strlen(handle->params.reg.scopelist); } handle->params.reg.attrlistlen = strlen(attrList); handle->params.reg.attrlist = attrList; handle->params.reg.callback = callback; handle->params.reg.cookie = cookie; #ifdef ENABLE_ASYNC_API /*----------------------------------------------*/ /* Check to see if we should be async or sync */ /*----------------------------------------------*/ if(handle->isAsync) { /* Copy all of the referenced parameters before making thread */ handle->params.reg.url = xstrdup(handle->params.reg.url); handle->params.reg.srvtype = xstrdup(handle->params.reg.url); handle->params.reg.scopelist = xstrdup(handle->params.reg.scopelist); handle->params.reg.attrlist = xstrdup(handle->params.reg.attrlist); /* make sure that the strdups did not fail */ if(handle->params.reg.url && handle->params.reg.srvtype && handle->params.reg.scopelist && handle->params.reg.attrlist) { result = ThreadCreate((ThreadStartProc)AsyncProcessSrvReg,handle); } else { result = SLP_MEMORY_ALLOC_FAILED; } if(result) { if(handle->params.reg.url) xfree((void*)handle->params.reg.url); if(handle->params.reg.srvtype) xfree((void*)handle->params.reg.srvtype); if(handle->params.reg.scopelist) xfree((void*)handle->params.reg.scopelist); if(handle->params.reg.attrlist) xfree((void*)handle->params.reg.attrlist); handle->inUse = SLP_FALSE; } } else #endif //ffdef ENABLE_ASYNC_API { result = ProcessSrvReg(handle); handle->inUse = SLP_FALSE; } if(parsedurl) SLPFree(parsedurl); return result; }
/** Register a service URL through OpenSLP. * * Registers the URL in @p pcSrvURL having the lifetime usLifetime with * the attribute list in pcAttrs. The @p pcAttrs list is a comma separated * list of attribute assignments in the wire format (including escaping * of reserved characters). The @p usLifetime parameter must be nonzero * and less than or equal to SLP_LIFETIME_MAXIMUM. If the @p fresh flag * is SLP_TRUE, then the registration is new (the SLP protocol FRESH flag * is set) and the registration replaces any existing registrations. * The @p pcSrvType parameter is a service type name and can be included * for service URLs that are not in the service: scheme. If the URL is * in the service: scheme, the @p pcSrvType parameter is ignored. If the * @p fresh flag is SLP_FALSE, then an existing registration is updated. * Rules for new and updated registrations, and the format for @p pcAttrs * and @p pcScopeList can be found in [RFC 2608]. Registrations and * updates take place in the language locale of the @p hSLP handle. * * @par * The API library is required to perform the operation in all scopes * obtained through configuration. * * @param[in] hSLP - The language-specific SLPHandle on which to register * the advertisement. * @param[in] srvUrl - The URL to register. May not be the empty string. * May not be NULL. Must conform to SLP Service URL syntax. * SLP_INVALID_REGISTRATION will be returned if not. * @param[in] lifetime - An unsigned short giving the life time of the * service advertisement, in seconds. The value must be an unsigned * integer less than or equal to SLP_LIFETIME_MAXIMUM, and greater * than zero. If SLP_LIFETIME_MAXIMUM is used, the registration * will remain for the life of the calling process. Also, OpenSLP, * will not allow registrations to be made with SLP_LIFETIME_MAXIMUM * unless SLP_REG_FLAG_WATCH_PID is also used. Note that RFC 2614 * defines this parameter as const unsigned short. The 'const' is * superfluous. * @param[in] srvType - The service type. If @p pURL is a "service:" * URL, then this parameter is ignored. (ALWAYS ignored since the SLP * Service URL syntax required for the @p pcSrvURL encapsulates the * service type.) * @param[in] attrList - A comma separated list of attribute assignment * expressions for the attributes of the advertisement. Use empty * string ("") for no attributes. * @param[in] fresh - An SLPBoolean that is SLP_TRUE if the registration * is new or SLP_FALSE if a RE-registration. Use of non-fresh * registrations is deprecated (post RFC 2614). SLP_TRUE must be * passed in for this parameter or SLP_BAD_PARAMETER will be returned. * It also appears that this flag has been overloaded to accept certain * specific values of "true" for internal purposes... (jmc) * @param[in] callback - A callback to report the operation completion * status. * @param[in] cookie - Memory passed to the callback code from the * client. May be NULL. * * @return If an error occurs in starting the operation, one of the * SLPError codes is returned. */ SLPEXP SLPError SLPAPI SLPReg( SLPHandle hSLP, const char * srvUrl, unsigned short lifetime, const char * srvType, const char * attrList, SLPBoolean fresh, SLPRegReport callback, void * cookie) { bool inuse; SLPError serr; SLPSrvURL * parsedurl = 0; SLPHandleInfo * handle = hSLP; /** @todo Add code to accept non- "service:" scheme * URL's - normalize with srvType parameter info. */ (void)srvType; /* not used yet */ /* Check for invalid parameters. */ SLP_ASSERT(handle != 0); SLP_ASSERT(handle->sig == SLP_HANDLE_SIG); SLP_ASSERT(srvUrl != 0); SLP_ASSERT(*srvUrl != 0); SLP_ASSERT(lifetime != 0); SLP_ASSERT(attrList != 0); SLP_ASSERT(callback != 0); if (handle == 0 || handle->sig != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || lifetime == 0 || attrList == 0 || callback == 0) return SLP_PARAMETER_BAD; /** @todo Handle non-fresh registrations in SLPReg. */ if (fresh == SLP_FALSE) return SLP_NOT_IMPLEMENTED; /* Check to see if the handle is in use. */ inuse = SLPSpinLockTryAcquire(&handle->inUse); SLP_ASSERT(!inuse); if (inuse) return SLP_HANDLE_IN_USE; /* Parse the srvurl - mainly for service type info. */ serr = SLPParseSrvURL(srvUrl, &parsedurl); if (serr) { SLPSpinLockRelease(&handle->inUse); return serr == SLP_PARSE_ERROR? SLP_INVALID_REGISTRATION: serr; } /* Set the handle up to reference parameters. */ handle->params.reg.fresh = fresh; handle->params.reg.lifetime = lifetime; handle->params.reg.urllen = strlen(srvUrl); handle->params.reg.url = srvUrl; handle->params.reg.srvtype = parsedurl->s_pcSrvType; handle->params.reg.srvtypelen = strlen(handle->params.reg.srvtype); handle->params.reg.scopelist = SLPPropertyGet("net.slp.useScopes", 0, 0); handle->params.reg.scopelistlen = strlen(handle->params.reg.scopelist); handle->params.reg.attrlistlen = strlen(attrList); handle->params.reg.attrlist = attrList; handle->params.reg.callback = callback; handle->params.reg.cookie = cookie; #ifdef ENABLE_ASYNC_API if (handle->isAsync) { /* Copy all of the referenced parameters before creating thread. */ handle->params.reg.url = xstrdup(handle->params.reg.url); handle->params.reg.srvtype = xstrdup(handle->params.reg.url); handle->params.reg.scopelist = xstrdup(handle->params.reg.scopelist); handle->params.reg.attrlist = xstrdup(handle->params.reg.attrlist); /* Ensure strdups and thread create succeed. */ if (handle->params.reg.url == 0 || handle->params.reg.srvtype == 0 || handle->params.reg.scopelist == 0 || handle->params.reg.attrlist == 0 || (handle->th = SLPThreadCreate((SLPThreadStartProc) AsyncProcessSrvReg, handle)) == 0) { serr = SLP_MEMORY_ALLOC_FAILED; xfree((void *)handle->params.reg.url); xfree((void *)handle->params.reg.srvtype); xfree((void *)handle->params.reg.scopelist); xfree((void *)handle->params.reg.attrlist); SLPSpinLockRelease(&handle->inUse); } } else #endif { /* Reference all the parameters. */ serr = ProcessSrvReg(handle); SLPSpinLockRelease(&handle->inUse); } SLPFree(parsedurl); return serr; }
/* * list_merge * * This function will build a list of unique elements. It assumes * that the items arriving with pcNewList are packed, for efficiency. * If the list grows too large, it will be grown to take in the new * string and 'breathing room' for further expansion. * * pcNewList The new list to merge in with the old one. * ppcList A pointer to the buffer with the list to be built onto. * piListLen The max size of the list list to be build onto. * iCheck If this is 0, don't check for duplicates. * * Returns: None. * * Side Effects: * * A call to this function can result in *ppcList (the buffer) being * reallocated and *piListLen (the max buffer size) being expanded.) */ EXPORT void list_merge(const char *pcNewList, char **ppcList, int *piListLen, int iCheck) { int offset = 0; char c, *pcScope; int initial = 0; if (!pcNewList) return; if (!ppcList) return; if (!*ppcList) { *ppcList = safe_malloc(strlen(pcNewList)+1,pcNewList,strlen(pcNewList)); *piListLen = strlen(*ppcList); return; } if (*piListLen == 0) initial = 1; /* suppresses initial comma in new lists */ if (!iCheck) { int iSLen = strlen(pcNewList); if ((iSLen + (int) strlen(*ppcList)+1) >= *piListLen) { /* too big? */ char *pcOld = *ppcList; *piListLen += iSLen + LISTINCR; *ppcList = safe_malloc(*piListLen,*ppcList,strlen(*ppcList)); SLPFree(pcOld); } if (!initial) slp_strcat(*ppcList,","); slp_strcat(*ppcList,pcNewList); return; } while((pcScope = get_next_string(",",pcNewList,&offset,&c))) { if (!list_intersection(pcScope,*ppcList)) { int iSLen = strlen(pcScope); if ((iSLen + (int) strlen(*ppcList)+1) >= *piListLen) { /* too big? */ char *pcOld = *ppcList; *piListLen += iSLen + LISTINCR; *ppcList = safe_malloc(*piListLen,*ppcList,strlen(*ppcList)); SLPFree(pcOld); } if (initial != 1) slp_strcat(*ppcList,","); /* supress initial comma */ slp_strcat(*ppcList,pcScope); /* append the scope not already on list */ } SLPFree(pcScope); } }
/*-------------------------------------------------------------------------*/ SLPBoolean KnownDADiscoveryCallback(SLPError errorcode, SLPMessage msg, void* cookie) /*-------------------------------------------------------------------------*/ { SLPSrvURL* srvurl; SLPDAEntry daentry; SLPDAEntry* entry; int* result; struct in_addr addr; struct hostent* he; result = (int*)cookie; if(errorcode == 0) { if(msg && msg->header.functionid == SLP_FUNCT_DAADVERT) { if(msg->body.daadvert.errorcode == 0) { /* NULL terminate scopelist */ *((char*)msg->body.daadvert.scopelist + msg->body.daadvert.scopelistlen) = 0; if(SLPParseSrvURL(msg->body.daadvert.url, &srvurl) == 0) { he = gethostbyname(srvurl->s_pcHost); if(he) { /* create a daentry and add it to the knownda list */ daentry.langtaglen = msg->header.langtaglen; daentry.langtag = msg->header.langtag; daentry.bootstamp = msg->body.daadvert.bootstamp; daentry.urllen = msg->body.daadvert.urllen; daentry.url = msg->body.daadvert.url; daentry.scopelistlen = msg->body.daadvert.scopelistlen; daentry.scopelist = msg->body.daadvert.scopelist; daentry.attrlistlen = msg->body.daadvert.attrlistlen; daentry.attrlist = msg->body.daadvert.attrlist; daentry.spilistlen = msg->body.daadvert.spilistlen; daentry.spilist = msg->body.daadvert.spilist; addr.s_addr = *((unsigned int*)(he->h_addr_list[0])); entry = SLPDAEntryCreate(&addr, &daentry); if(entry) { KnownDAListAdd(&G_KnownDACache, entry); (*result) = (*result) + 1; } if(msg->header.flags & SLP_FLAG_MCAST) { return 0; } } SLPFree(srvurl); } } else if(msg->body.daadvert.errorcode == SLP_ERROR_INTERNAL_ERROR) { /* SLP_ERROR_INTERNAL_ERROR is a "end of stream marker for */ /* loobpack IPC */ return 0; } } } return 1; }
/*-------------------------------------------------------------------------*/ 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) { he = gethostbyname(srvurl->s_pcHost); SLPFree(srvurl); if(he) { /* Reset the peer to the one in the URL */ replymsg->peer.sin_addr.s_addr = *((unsigned int*)(he->h_addr_list[0])); (*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; }