Example #1
0
/** 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;
}
Example #2
0
/*-------------------------------------------------------------------------*/
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;
}