/** Process a DA service request message. * * @param[in] message - The message to process. * @param[out] sendbuf - The response buffer to fill. * @param[in] errorcode - The error code from the client request. * * @return Zero on success, or a non-zero SLP error on failure. * * @internal */ static int ProcessDASrvRqst(SLPMessage * message, SLPBuffer * sendbuf, int errorcode) { SLPBuffer tmp = 0; SLPMessage * msg = 0; void * eh = 0; /* TODO should really be a configurable property, maybe G_SlpdProperty.MTU? Left at 4096 to retain same behaviour */ size_t initial_buffer_size = 4096; size_t grow_size = initial_buffer_size; /* Special case for when libslp asks slpd (through the loopback) about a known DAs. Fill sendbuf with DAAdverts from all known DAs. */ if (SLPNetIsLoopback(&message->peer)) { *sendbuf = SLPBufferRealloc(*sendbuf, initial_buffer_size); if (*sendbuf == 0) return SLP_ERROR_INTERNAL_ERROR; if (errorcode == 0) { /* Note: The weird *sendbuf code is making a single SLPBuffer that contains multiple DAAdverts. This is a special process that only happens for the DA SrvRqst through loopback to the SLPAPI */ /*If we are a DA, always have ourself at the start of the list, so the lib requests can be handled locally for speed */ if(G_SlpdProperty.isDA) { struct sockaddr_storage loaddr; if(SLPNetIsIPV4()) { int addr = INADDR_LOOPBACK; SLPNetSetAddr(&loaddr, AF_INET, G_SlpdProperty.port, &addr); } else { SLPNetSetAddr(&loaddr, AF_INET6, G_SlpdProperty.port, &slp_in6addr_loopback); } if(0 == SLPDKnownDAGenerateMyDAAdvert(&loaddr, 0, 0, 0, message->header.xid, &tmp)) { memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); SLPBufferFree(tmp); tmp = 0; } else { SLPDLog("Unable to add initial DAAdvert due to error\n"); } } eh = SLPDKnownDAEnumStart(); if (eh) { while (1) { /* iterate over all database entries */ if (SLPDKnownDAEnum(eh, &msg, &tmp) == 0) { break; } /* if we resize succesfully.. */ if( CheckAndResizeBuffer(sendbuf, tmp, grow_size) == 0 ) { /* buffer should now be resized to an appropriate size to handle all current database entries */ /* TRICKY: Fix up the XID and clear the flags. */ tmp->curpos = tmp->start + 10; TO_UINT16(tmp->curpos, message->header.xid); if (*(tmp->start) == 1) *(tmp->start + 4) = 0; else TO_UINT16(tmp->start + 5, 0); /* copy all data out of tmp into the sendbuf */ memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); /* increment the current position in sendbuf */ (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); } else { errorcode = SLP_ERROR_INTERNAL_ERROR; } } SLPDKnownDAEnumEnd(eh); } /* tmp can store database entries which should not be freed by anyone else so reset the pointer to prevent double deletion */ tmp = 0; /* Tack on a "terminator" DAAdvert Note that this function *always* returns the error code passed as its second parameter (or SLP_ERROR_INTERNAL_ERROR if the buffer fails to resize) The errorcode is also inserted into the srvrply header by this function */ SLPDKnownDAGenerateMyDAAdvert(&message->localaddr, SLP_ERROR_INTERNAL_ERROR, 0, 0, message->header.xid, &tmp); /* if we resize succesfully.. */ if ( CheckAndResizeBuffer(sendbuf, tmp, grow_size) == 0 ) { memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); /* mark the end of the sendbuf */ (*sendbuf)->end = (*sendbuf)->curpos; } else { errorcode = SLP_ERROR_INTERNAL_ERROR; } SLPBufferFree(tmp); tmp = 0; } return errorcode; } /* Normal case where a remote Agent asks for a DA */ *sendbuf = SLPBufferRealloc(*sendbuf, G_SlpdProperty.MTU); if (*sendbuf == 0) return SLP_ERROR_INTERNAL_ERROR; if (G_SlpdProperty.isDA) { if (message->body.srvrqst.scopelistlen == 0 || SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { errorcode = SLPDKnownDAGenerateMyDAAdvert(&message->localaddr, errorcode, 0, 0, message->header.xid, sendbuf); } else errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } else errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED; /* don't return errorcodes to multicast messages */ if (errorcode != 0) { if (message->header.flags & SLP_FLAG_MCAST || SLPNetIsMCast(&(message->peer))) (*sendbuf)->end = (*sendbuf)->start; } return errorcode; }
/*-------------------------------------------------------------------------*/ int ProcessDASrvRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { SLPDAEntry daentry; SLPBuffer tmp = 0; SLPDAEntry* entry = 0; void* i = 0; /* set up local data */ memset(&daentry,0,sizeof(daentry)); /*---------------------------------------------------------------------*/ /* Special case for when libslp asks slpd (through the loopback) about */ /* a known DAs. Fill sendbuf with DAAdverts from all known DAs. */ /*---------------------------------------------------------------------*/ if(ISLOCAL(peeraddr->sin_addr)) { /* TODO: be smarter about how much memory is allocated here! */ /* 4096 may not be big enough to handle all DAAdverts */ *sendbuf = SLPBufferRealloc(*sendbuf, 4096); if(*sendbuf == 0) { return SLP_ERROR_INTERNAL_ERROR; } if(errorcode == 0) { /* Note: The weird *sendbuf code is making a single SLPBuffer */ /* that contains multiple DAAdverts. This is a special */ /* process that only happens for the DA SrvRqst through */ /* loopback to the SLPAPI */ while(SLPDKnownDAEnum(&i,&entry) == 0) { if(SLPDKnownDAEntryToDAAdvert(errorcode, message->header.xid, entry, &tmp) == 0) { if(((*sendbuf)->curpos) + (tmp->end - tmp->start) > (*sendbuf)->end) { break; } memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); } } /* Tack on a "terminator" DAAdvert */ SLPDKnownDAEntryToDAAdvert(SLP_ERROR_INTERNAL_ERROR, message->header.xid, &daentry, &tmp); if(((*sendbuf)->curpos) + (tmp->end - tmp->start) <= (*sendbuf)->end) { memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); } /* mark the end of the sendbuf */ (*sendbuf)->end = (*sendbuf)->curpos; if(tmp) { SLPBufferFree(tmp); } } return errorcode; } /*---------------------------------------------------------------------*/ /* Normal case where a remote Agent asks for a DA */ /*---------------------------------------------------------------------*/ if(G_SlpdProperty.isDA) { if(message->body.srvrqst.scopelistlen == 0 || SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /* fill out real structure */ G_SlpdProperty.DATimestamp += 1; daentry.bootstamp = G_SlpdProperty.DATimestamp; daentry.langtaglen = G_SlpdProperty.localeLen; daentry.langtag = (char*)G_SlpdProperty.locale; daentry.urllen = G_SlpdProperty.myUrlLen; daentry.url = (char*)G_SlpdProperty.myUrl; daentry.scopelistlen = G_SlpdProperty.useScopesLen; daentry.scopelist = (char*)G_SlpdProperty.useScopes; daentry.attrlistlen = 0; daentry.attrlist = 0; daentry.spilistlen = 0; daentry.spilist = 0; } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } } else { errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED; } /* don't return errorcodes to multicast messages */ if(errorcode != 0) { if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { (*sendbuf)->end = (*sendbuf)->start; return errorcode; } } errorcode = SLPDKnownDAEntryToDAAdvert(errorcode, message->header.xid, &daentry, sendbuf); return errorcode; }