Example #1
0
/** SLPReg callback routine for NetworkRqstRply.
 *
 * @param[in] errorcode - The network operation SLPError result.
 * @param[in] peeraddr - The network address of the responder.
 * @param[in] replybuf - The response buffer from the network request.
 * @param[in] cookie - Callback context data from ProcessSrvReg.
 *
 * @return SLP_FALSE (to stop any iterative callbacks).
 *
 * @note The SLPv2 wire protocol error codes are negated values of SLP
 * API error codes (SLPError values). Thus, the algorithm for converting 
 * from an SLPv2 wire protocol error to a client SLPReg error is to simply 
 * negate the wire protocol error value and cast the result to an SLPError.
 *
 * @todo Verify that no non-SLPError wire values make it back to this
 * routine, to be mis-converted into a non-existent SLPError value.
 *
 * @internal
 */
static SLPBoolean CallbackSrvReg(SLPError errorcode, 
      void * peeraddr, SLPBuffer replybuf, void * cookie)
{
   SLPHandleInfo * handle = (SLPHandleInfo *)cookie;

   /* Check the errorcode and bail if it is set. */
   if (errorcode == 0)
   {
      /* Parse the replybuf into a message. */
      SLPMessage * replymsg = SLPMessageAlloc();
      if (replymsg)
      {
         errorcode = (SLPError)(-SLPMessageParseBuffer(
               peeraddr, 0, replybuf, replymsg));
         if (errorcode == 0 
               && replymsg->header.functionid == SLP_FUNCT_SRVACK)
            errorcode = (SLPError)(-replymsg->body.srvack.errorcode);
         else
            errorcode = SLP_NETWORK_ERROR;
         SLPMessageFree(replymsg);
      }
      else
         errorcode = SLP_MEMORY_ALLOC_FAILED;
   }

   /* Call the user's callback function. */
   handle->params.reg.callback(handle, errorcode, 
         handle->params.reg.cookie);

   return SLP_FALSE;
}
Example #2
0
/** SLPFindSrvTypes callback routine for NetworkRqstRply.
 *
 * @param[in] errorcode - The network operation error code.
 * @param[in] peerinfo - The network address of the responder.
 * @param[in] replybuf - The response buffer from the network request.
 * @param[in] cookie - Callback context data from ProcessSrvReg.
 *
 * @return SLP_FALSE (to stop any iterative callbacks).
 *
 * @internal
 */
static SLPBoolean ProcessSrvTypeRplyCallback(SLPError errorcode, 
      void * peerinfo, SLPBuffer replybuf, void * cookie)
{
   SLPMessage * replymsg;
   SLPBoolean result = SLP_TRUE;
   SLPHandleInfo * handle = (SLPHandleInfo *)cookie;

   /* Check the errorcode and bail if it is set. */
   if (errorcode)
      return CollateToSLPSrvTypeCallback(handle, 0, errorcode);

   /* Parse the replybuf. */
   replymsg = SLPMessageAlloc();
   if (replymsg)
   {
      if (!SLPMessageParseBuffer(peerinfo, 0, replybuf, replymsg)
            && replymsg->header.functionid == SLP_FUNCT_SRVTYPERPLY 
            && !replymsg->body.srvtyperply.errorcode)
      {
         SLPSrvTypeRply * srvtyperply = &replymsg->body.srvtyperply;
         if (srvtyperply->srvtypelistlen)
            result = CollateToSLPSrvTypeCallback((SLPHandle)handle, 
                  srvtyperply->srvtypelist, srvtyperply->errorcode * -1);
      }
      SLPMessageFree(replymsg);
   }
   return result;
}
Example #3
0
/*=========================================================================*/
void SLPDLogTraceMsg(const char* prefix,
                     struct sockaddr_in* peeraddr,
                     SLPBuffer buf)
/*=========================================================================*/
{
    SLPMessage msg;
    if(G_SlpdProperty.traceMsg)
    {
        msg = SLPMessageAlloc();
        if(msg)
        {
            if(SLPMessageParseBuffer(buf,msg) == 0)
            {
                SLPLog("----------------------------------------\n");
                SLPLog("traceMsg %s:\n",prefix);
                SLPLog("----------------------------------------\n");
                SLPDLogPeerAddr(peeraddr);
                SLPDLogMessage(msg);
                SLPLog("\n");
            }
        }

        SLPMessageFree(msg);
    }
}
Example #4
0
/*----------------------------------------------------------------------------*/
SLPBoolean ProcessSrvTypeRplyCallback(SLPError errorcode, 
                                      struct sockaddr_in* peerinfo,
                                      SLPBuffer replybuf,
                                      void* cookie)
/*----------------------------------------------------------------------------*/
{
    SLPMessage      replymsg;
    SLPSrvTypeRply* srvtyperply;
    PSLPHandleInfo  handle      = (PSLPHandleInfo) cookie;
    SLPBoolean      result      = SLP_TRUE;

    /*-------------------------------------------*/
    /* Check the errorcode and bail if it is set */
    /*-------------------------------------------*/
    if(errorcode)
    {
        return ColateSrvTypeCallback((SLPHandle)handle,
                                     0,
                                     errorcode,
                                     handle->params.findsrvtypes.cookie);
    }

    /*--------------------*/
    /* Parse the replybuf */
    /*--------------------*/
    replymsg = SLPMessageAlloc();
    if(replymsg)
    {
        if(SLPMessageParseBuffer(peerinfo,replybuf,replymsg) == 0 &&
           replymsg->header.functionid == SLP_FUNCT_SRVTYPERPLY &&
           replymsg->body.srvtyperply.errorcode == 0)
        {

            srvtyperply = &(replymsg->body.srvtyperply);
            if(srvtyperply->srvtypelistlen)
            {
                /*------------------------------------------*/
                /* Send the service type list to the caller */
                /*------------------------------------------*/
                /* TRICKY: null terminate the srvtypelist by setting the last byte 0 */
                ((char*)(srvtyperply->srvtypelist))[srvtyperply->srvtypelistlen] = 0;
                
                /* Call the callback function */
                result = ColateSrvTypeCallback((SLPHandle)handle,
                                               srvtyperply->srvtypelist,
                                               srvtyperply->errorcode * - 1,
                                               handle->params.findsrvtypes.cookie);
            }
        }
        
        SLPMessageFree(replymsg);
    }
    
    return result;
}
Example #5
0
/*-------------------------------------------------------------------------*/
SLPBoolean CallbackSrvReg(SLPError errorcode,
                          struct sockaddr_in* peerinfo,
                          SLPBuffer replybuf, 
                          void* cookie)
/*-------------------------------------------------------------------------*/
{
    SLPMessage      replymsg;
    PSLPHandleInfo  handle      = (PSLPHandleInfo) cookie;

    /*-------------------------------------------*/
    /* Check the errorcode and bail if it is set */
    /*-------------------------------------------*/
    if(errorcode == 0)
    {
        /*--------------------*/
        /* Parse the replybuf */
        /*--------------------*/
        replymsg = SLPMessageAlloc();
        if(replymsg)
        {
            errorcode = SLPMessageParseBuffer(peerinfo,replybuf,replymsg);
            if(errorcode == 0)
            {
                if(replymsg->header.functionid == SLP_FUNCT_SRVACK)
                {
                    errorcode = replymsg->body.srvack.errorcode * - 1;
                }
            }
    
            SLPMessageFree(replymsg);
        }
        else
        {
            errorcode = SLP_MEMORY_ALLOC_FAILED;
        }
    }

    /*----------------------------*/
    /* Call the callback function */
    /*----------------------------*/
    handle->params.reg.callback((SLPHandle)handle,
                                errorcode,
                                handle->params.reg.cookie);
    
    return SLP_FALSE;
}
Example #6
0
/*-------------------------------------------------------------------------*/ 
SLPError ProcessSrvDeReg(PSLPHandleInfo handle)
/*-------------------------------------------------------------------------*/
{
    struct timeval      timeout;
    struct sockaddr     peeraddr;
    int                 peeraddrlen = sizeof(peeraddr);
    int                 size        = 0;
    SLPError            error       = 0;
    SLPBuffer           buf         = 0;
    SLPMessage          msg         = 0;
    int                 xid         = XidGenerate();
    
    
    /*-----------------------*/
    /* allocate a SLPMessage */
    /*-----------------------*/
    msg = SLPMessageAlloc();
    if(msg == 0)
    {
        error = SLP_MEMORY_ALLOC_FAILED;
        goto FINISHED;
    }


    /*-------------------------------------------------------------*/
    /* ensure the buffer is big enough to handle the whole srvreg  */
    /*-------------------------------------------------------------*/
    size = handle->langtaglen + 14;                 /* 14 bytes for header  */

    size += handle->params.dereg.scopelistlen + 2; /*  2 bytes for len field*/
    size += handle->params.dereg.urllen + 8;       /*  1 byte for reserved  */
                                                   /*  2 bytes for lifetime */
                                                   /*  2 bytes for urllen   */
                                                   /*  1 byte for authcount */
    size += 2;                                     /*  2 bytes for taglistlen*/
    
    
    
    /* TODO: Fix this for authentication */
    
    buf = SLPBufferAlloc(size);
    if(buf == 0)
    {
        error = SLP_MEMORY_ALLOC_FAILED;
        goto FINISHED;
    }

    /*----------------*/
    /* Add the header */
    /*----------------*/
    /*version*/
    *(buf->start)       = 2;
    /*function id*/
    *(buf->start + 1)   = SLP_FUNCT_SRVDEREG;
    /*length*/
    ToUINT24(buf->start + 2,size);
    /*flags*/
    ToUINT16(buf->start + 5, 0);
    /*ext offset*/
    ToUINT24(buf->start + 7,0);
    /*xid*/
    ToUINT16(buf->start + 10,xid);
    /*lang tag len*/
    ToUINT16(buf->start + 12,handle->langtaglen);
    /*lang tag*/
    memcpy(buf->start + 14,
           handle->langtag,
           handle->langtaglen);


    /*--------------------------*/
    /* Add rest of the SrvDeReg */
    /*--------------------------*/
    buf->curpos = buf->curpos + handle->langtaglen + 14;
    
    /* scope list */
    ToUINT16(buf->curpos,handle->params.dereg.scopelistlen);
    buf->curpos = buf->curpos + 2;
    memcpy(buf->curpos,
           handle->params.dereg.scopelist,
           handle->params.dereg.scopelistlen);
    buf->curpos = buf->curpos + handle->params.dereg.scopelistlen;

    /* url-entry reserved */
    *buf->curpos = 0;        
    buf->curpos = buf->curpos + 1;
    /* url-entry lifetime */
    ToUINT16(buf->curpos, 0);
    buf->curpos = buf->curpos + 2;
    /* url-entry urllen */
    ToUINT16(buf->curpos,handle->params.dereg.urllen);
    buf->curpos = buf->curpos + 2;
    /* url-entry url */
    memcpy(buf->curpos,
           handle->params.dereg.url,
           handle->params.dereg.urllen);
    buf->curpos = buf->curpos + handle->params.dereg.urllen;
    /* url-entry authcount */
    *buf->curpos = 0;        
    buf->curpos = buf->curpos + 1;
    /* TODO: put in urlentry authentication stuff too */
    
    /* TODO: put tag list stuff in*/
    ToUINT16(buf->curpos,0);

    
    /*------------------------*/
    /* Send the SrvDeReg      */
    /*------------------------*/
    timeout.tv_sec = atoi(SLPGetProperty("net.slp.unicastMaximumWait")) / 1000;  
    timeout.tv_usec = 0;        
    buf->curpos = buf->start;
    error = NetworkSendMessage(handle->slpdsock,
                              buf,
                              &timeout,
                              &(handle->slpdaddr),
                              sizeof(handle->slpdaddr));
    if(error == SLP_OK)
    {
        /* Recv the SrvAck */
        error = NetworkRecvMessage(handle->slpdsock,
                                  buf,
                                  &timeout,
                                  &peeraddr,
                                  &peeraddrlen);
        if(error == SLP_OK)
        {
            /* parse the SrvAck message */
            error = SLPMessageParseBuffer(buf,msg);
            if(error == SLP_OK)
            {
                if(msg->header.xid == xid && 
                   msg->header.functionid == SLP_FUNCT_SRVACK)
                {
                    /* map and use errorcode from message */
                    error = -(msg->body.srvack.errorcode);
                }
                else
                {
                    error = SLP_NETWORK_ERROR;
                }
            }
        }
    }
    

    FINISHED:

    /* call callback function */
    handle->params.dereg.callback((SLPHandle)handle,
                                     error,
                                     handle->params.dereg.cookie);
    
    /* free resources */
    SLPBufferFree(buf);
    SLPMessageFree(msg);
        
    return 0;
}
Example #7
0
/*=========================================================================*/
void SLPDLogMessage(int msglogflags,
                    struct sockaddr_storage* peerinfo,
                    struct sockaddr_storage* localaddr,
                    SLPBuffer buf)
/* Log record of receiving or sending an SLP Message.  Logging will only   */
/* occur if message logging is enabled G_SlpProperty.traceMsg != 0         */
/*                                                                         */
/* msglogflags   (IN) What type of message to log                          */
/*                                                                         */
/* peerinfo (IN) the source or destination peer                            */
/*                                                                         */
/* peerinfo (IN) the local address                                         */
/*                                                                         */
/* msg      (IN) the message to log                                        */
/*                                                                         */
/* Returns: none                                                           */
/*=========================================================================*/
{
    SLPMessage msg;
    char addr_str[INET6_ADDRSTRLEN];

    if (peerinfo == NULL ||
        buf == NULL)
    {
        return;
    }

    if ((G_SlpdProperty.traceMsg && (msglogflags & SLPDLOG_TRACEMSG)) ||
        (G_SlpdProperty.traceDrop && (msglogflags & SLPDLOG_TRACEDROP)) )
    {
        /* Don't log localhost traffic since it is probably IPC */
        /* and don't log empty messages                         */
        if (!SLPNetIsLocal(peerinfo) && buf->end != buf->start)
        {
            msg = SLPMessageAlloc();
            if (msg)
            {
                SLPDLog("\n");
                SLPDLogTime();
                SLPDLog("MESSAGE - ");
                if (msglogflags == SLPDLOG_TRACEMSG_OUT)
                {
                    SLPDLog("Trace message (OUT)\n");
                }
                else if (msglogflags == SLPDLOG_TRACEMSG_IN)
                {
                    SLPDLog("Trace message (IN)\n");
                }
                else if (msglogflags == SLPDLOG_TRACEDROP)
                {
                    SLPDLog("Dropped message (following message silently ignored)\n");
                }
                else
                {
                    SLPDLog("\n");
                }

                if (SLPMessageParseBuffer(peerinfo,localaddr,buf,msg) == 0)
                {
                    SLPDLogMessageInternals(msg);
                }
                else
                {
                    SLPDLog("Message parsing failed\n");
                    SLPDLog("Peer: \n");
                    SLPDLog("   IP address: %s\n", SLPNetSockAddrStorageToString(&(msg->peer), addr_str, sizeof(addr_str)));
                }

                SLPMessageFree(msg);
            }
        }
    }
}
Example #8
0
/*=========================================================================*/
int SLPDProcessMessage(SLPDPeerInfo* peerinfo,
                       SLPBuffer recvbuf,
                       SLPBuffer sendbuf)
/* Processes the recvbuf and places the results in sendbuf                 */
/*                                                                         */
/* recvfd   - the socket the message was received on                       */
/*                                                                         */
/* recvbuf  - message to process                                           */
/*                                                                         */
/* sendbuf  - results of the processed message                             */
/*                                                                         */
/* Returns  - zero on success SLP_ERROR_PARSE_ERROR or                     */
/*            SLP_ERROR_INTERNAL_ERROR on ENOMEM.                          */
/*=========================================================================*/
{
    SLPMessage  message   = 0;
    int         result  = 0;

    message = SLPMessageAlloc();
    if(message == 0)
    {
        return SLP_ERROR_INTERNAL_ERROR;
    }

    result = SLPMessageParseBuffer(recvbuf, message);
    if(result == 0)
    {
        switch(message->header.functionid)
        {
        case SLP_FUNCT_SRVRQST:
            ProcessSrvRqst(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_SRVREG:
            ProcessSrvReg(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_SRVDEREG:
            ProcessSrvDeReg(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_SRVACK:
            ProcessSrvAck(peerinfo,message,sendbuf);        
            break;
    
        case SLP_FUNCT_ATTRRQST:
            ProcessAttrRqst(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_DAADVERT:
            ProcessDAAdvert(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_SRVTYPERQST:
            ProcessSrvTypeRqst(peerinfo,message,sendbuf);
            break;
    
        case SLP_FUNCT_SAADVERT:
            ProcessSAAdvert(peerinfo,message,sendbuf);
            break;
    
        default:
            /* this will NEVER happen */
            break;
        }

        /* Log traceMsg of message was received and the one that will be sent */
        if(G_SlpdProperty.traceMsg)
        {
            SLPDLogTraceMsg(peerinfo,recvbuf,sendbuf);
        }
    }
    else
    {
        /* TODO: Log here? */
    }
    
    SLPMessageFree(message);

    return result;
}                
Example #9
0
/*-------------------------------------------------------------------------*/
SLPBoolean ProcessSrvRplyCallback(SLPError errorcode,
                                  struct sockaddr_in* peerinfo,
                                  SLPBuffer replybuf,
                                  void* cookie)
/*-------------------------------------------------------------------------*/
{
    int             i;
    SLPUrlEntry*    urlentry;
    SLPMessage      replymsg;
    PSLPHandleInfo  handle      = (PSLPHandleInfo) cookie;
    SLPBoolean      result      = SLP_TRUE;

#ifdef ENABLE_SLPv2_SECURITY  
    int             securityenabled;
    securityenabled = SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"));
#endif

    /*-------------------------------------------*/
    /* Check the errorcode and bail if it is set */
    /*-------------------------------------------*/
    if(errorcode != SLP_OK)
    {
        return ColateSLPSrvURLCallback((SLPHandle)handle,
                                       0,
                                       0,
                                       errorcode,
                                       handle->params.findsrvs.cookie);
    }

    /*--------------------*/
    /* Parse the replybuf */
    /*--------------------*/
    replymsg = SLPMessageAlloc();
    if(replymsg)
    {
        if(SLPMessageParseBuffer(peerinfo,replybuf,replymsg) == 0)
        {
            if(replymsg->header.functionid == SLP_FUNCT_SRVRPLY &&
               replymsg->body.srvrply.errorcode == 0)
            {
                urlentry = replymsg->body.srvrply.urlarray;
            
                for(i=0;i<replymsg->body.srvrply.urlcount;i++)
                {
                    
#ifdef ENABLE_SLPv2_SECURITY
                    /*-------------------------------*/
                    /* Validate the authblocks       */
                    /*-------------------------------*/
                    if(securityenabled &&
                       SLPAuthVerifyUrl(handle->hspi,
                                        1,
                                        &(urlentry[i])))
                    {
                        /* authentication failed skip this URLEntry */
                        continue;
                    }
#endif
                    /*--------------------------------*/
                    /* Send the URL to the API caller */
                    /*--------------------------------*/
                    /* TRICKY: null terminate the url by setting the authcount to 0 */
                    ((char*)(urlentry[i].url))[urlentry[i].urllen] = 0;
    
                    result = ColateSLPSrvURLCallback((SLPHandle)handle,
                                                     urlentry[i].url,
                                                     (unsigned short)urlentry[i].lifetime,
                                                     SLP_OK,
                                                     handle->params.findsrvs.cookie);
                    if(result == SLP_FALSE)
                    {
                        break;
                    }
                } 
            }
            else if(replymsg->header.functionid == SLP_FUNCT_DAADVERT &&
                    replymsg->body.daadvert.errorcode == 0)
            {
#ifdef ENABLE_SLPv2_SECURITY
                if(securityenabled &&
                   SLPAuthVerifyDAAdvert(handle->hspi,
                                         1,
                                         &(replymsg->body.daadvert)))
                {
                    /* Verification failed. Ignore message */
                    SLPMessageFree(replymsg);
                    return SLP_TRUE;
                }
#endif

                ((char*)(replymsg->body.daadvert.url))[replymsg->body.daadvert.urllen] = 0;
                result = ColateSLPSrvURLCallback((SLPHandle)handle,
                                                 replymsg->body.daadvert.url,
                                                 SLP_LIFETIME_MAXIMUM,
                                                 SLP_OK,
                                                 handle->params.findsrvs.cookie);
            }
            else if(replymsg->header.functionid == SLP_FUNCT_SAADVERT)
            {

#ifdef ENABLE_SLPv2_SECURITY
                if(securityenabled &&
                   SLPAuthVerifySAAdvert(handle->hspi,
                                         1,
                                         &(replymsg->body.saadvert)))
                {
                    /* Verification failed. Ignore message */
                    SLPMessageFree(replymsg);
                    return SLP_TRUE;
                }
#endif

                ((char*)(replymsg->body.saadvert.url))[replymsg->body.saadvert.urllen] = 0;
                result = ColateSLPSrvURLCallback((SLPHandle)handle,
                                                 replymsg->body.saadvert.url,
                                                 SLP_LIFETIME_MAXIMUM,
                                                 SLP_OK,
                                                 handle->params.findsrvs.cookie);

            }
        }
        
        SLPMessageFree(replymsg);
    }
    
    return result;
}
Example #10
0
/** SLPFindSrvs callback routine for NetworkRqstRply.
 *
 * @param[in] errorcode - The network operation error code.
 * @param[in] peeraddr - The network address of the responder.
 * @param[in] replybuf - The response buffer from the network request.
 * @param[in] cookie - Callback context data from ProcessSrvReg.
 *
 * @return SLP_FALSE (to stop any iterative callbacks).
 *
 * @internal
 */
static SLPBoolean ProcessSrvRplyCallback(SLPError errorcode, 
      void * peeraddr, SLPBuffer replybuf, void * cookie)
{
   SLPMessage * replymsg;
   SLPBoolean result = SLP_TRUE;
   SLPHandleInfo * handle = (SLPHandleInfo *)cookie;

#ifdef ENABLE_SLPv2_SECURITY
   SLPBoolean securityEnabled = SLPPropertyAsBoolean("net.slp.securityEnabled");
#endif

   /* Check the errorcode and bail if it is set. */
   if (errorcode != SLP_OK)
      return CollateToSLPSrvURLCallback(handle, 0, 0, errorcode);

   /* parse the replybuf */
   replymsg = SLPMessageAlloc();
   if (replymsg)
   {
      if (!SLPMessageParseBuffer(peeraddr, 0, replybuf, replymsg))
      {
         if (replymsg->header.functionid == SLP_FUNCT_SRVRPLY 
               && replymsg->body.srvrply.errorcode == 0)
         {
            int i;
            SLPUrlEntry * urlentry = replymsg->body.srvrply.urlarray;

            for (i = 0; i < replymsg->body.srvrply.urlcount; i++)
            {
#ifdef ENABLE_SLPv2_SECURITY
               /* Validate the service authblocks. */
               if (securityEnabled 
                     && SLPAuthVerifyUrl(handle->hspi, 1, &urlentry[i]))
                  continue; /* Authentication failed, skip this URLEntry. */
#endif
               result = CollateToSLPSrvURLCallback(handle, urlentry[i].url, 
                     (unsigned short)urlentry[i].lifetime, SLP_OK);
               if (result == SLP_FALSE)
                  break;
            } 
         }
         else if (replymsg->header.functionid == SLP_FUNCT_DAADVERT 
               && replymsg->body.daadvert.errorcode == 0)
         {
#ifdef ENABLE_SLPv2_SECURITY
            if (securityEnabled && SLPAuthVerifyDAAdvert(handle->hspi, 
                  1, &replymsg->body.daadvert))
            {
               /* Verification failed. Ignore message. */
               SLPMessageFree(replymsg);
               return SLP_TRUE;
            }
#endif
            result = CollateToSLPSrvURLCallback(handle, 
                  replymsg->body.daadvert.url, SLP_LIFETIME_MAXIMUM, 
                  SLP_OK);
         }
         else if (replymsg->header.functionid == SLP_FUNCT_SAADVERT)
         {
#ifdef ENABLE_SLPv2_SECURITY
            if (securityEnabled && SLPAuthVerifySAAdvert(handle->hspi, 1, 
                  &replymsg->body.saadvert))
            {
               /* Verification failed. Ignore message. */
               SLPMessageFree(replymsg);
               return SLP_TRUE;
            }
#endif
            result = CollateToSLPSrvURLCallback(handle, 
                  replymsg->body.saadvert.url, SLP_LIFETIME_MAXIMUM, 
                  SLP_OK);
         }
      }
      SLPMessageFree(replymsg);
   }
   return result;
}
Example #11
0
/** Processes the recvbuf and places the results in sendbuf
 *
 * @param[in] peerinfo - The remote address the message was received from.
 * @param[in] localaddr - The local address the message was received on.
 * @param[in] recvbuf - The message to process.
 * @param[out] sendbuf - The address of storage for the results of the 
 *    processed message.
 * @param[out] sendlist - if non-0, this function will prune the message 
 *    with the processed xid from the sendlist.
 *
 * @return Zero on success if @p sendbuf contains a response to send, 
 *    or a non-zero value if @p sendbuf does not contain a response
 *    to send.
 */
int SLPDProcessMessage(struct sockaddr_storage * peerinfo, 
      struct sockaddr_storage * localaddr, SLPBuffer recvbuf,
      SLPBuffer * sendbuf, SLPList * psendlist)
{
   SLPHeader header;
   SLPMessage * message = 0;
   int errorcode = 0;

#ifdef DEBUG
   char addr_str[INET6_ADDRSTRLEN];
#endif

   SLPDLogMessage(SLPDLOG_TRACEMSG_IN, peerinfo, localaddr, recvbuf);

   /* set the sendbuf empty */
   if (*sendbuf)
      (*sendbuf)->end = (*sendbuf)->start;

   /* zero out the header before parsing it */
   memset(&header, 0, sizeof(header));

   /* Parse just the message header */
   recvbuf->curpos = recvbuf->start;
   errorcode = SLPMessageParseHeader(recvbuf, &header);

   /* Reset the buffer "curpos" pointer so that full message can be 
      parsed later 
    */
   recvbuf->curpos = recvbuf->start;

#if defined(ENABLE_SLPv1)   
   /* if version == 1 and the header was correct then parse message as a version 1 message */
   if ((errorcode == 0) && (header.version == 1))
      errorcode = SLPDv1ProcessMessage(peerinfo, recvbuf, sendbuf);
   else
#endif
   if (errorcode == 0)
   {
      /* TRICKY: Duplicate SRVREG recvbufs *before* parsing them
       * we do this because we are going to keep track of in the 
       * registration database.
       */
      if (header.functionid == SLP_FUNCT_SRVREG 
            || header.functionid == SLP_FUNCT_DAADVERT)
      {
         recvbuf = SLPBufferDup(recvbuf);
         if (recvbuf == 0)
            return SLP_ERROR_INTERNAL_ERROR;
      }

      /* Allocate the message descriptor */
      message = SLPMessageAlloc();
      if (message)
      {
         /* Parse the message and fill out the message descriptor */
         errorcode = SLPMessageParseBuffer(peerinfo, localaddr,
               recvbuf, message);
         if (errorcode == 0)
         {
            /* Process messages based on type */
            switch (message->header.functionid)
            {
               case SLP_FUNCT_SRVRQST:
                  errorcode = ProcessSrvRqst(message, sendbuf, errorcode);
                  break;

               case SLP_FUNCT_SRVREG:
                  errorcode = ProcessSrvReg(message, recvbuf, 
                        sendbuf, errorcode);
                  if (errorcode == 0)
                     SLPDKnownDAEcho(message, recvbuf);         
                  break;

               case SLP_FUNCT_SRVDEREG:
                  errorcode = ProcessSrvDeReg(message, sendbuf, errorcode);
                  if (errorcode == 0)
                     SLPDKnownDAEcho(message, recvbuf);         
                  break;

               case SLP_FUNCT_SRVACK:
                  errorcode = ProcessSrvAck(message, sendbuf, errorcode);
                  break;

               case SLP_FUNCT_ATTRRQST:
                  errorcode = ProcessAttrRqst(message, sendbuf, errorcode);
                  break;

               case SLP_FUNCT_DAADVERT:
                  errorcode = ProcessDAAdvert(message, recvbuf, 
                        sendbuf, errorcode);
                  break;

               case SLP_FUNCT_SRVTYPERQST:
                  errorcode = ProcessSrvTypeRqst(message, sendbuf, errorcode);
                  break;

               case SLP_FUNCT_SAADVERT:
                  errorcode = ProcessSAAdvert(message, sendbuf, errorcode);
                  break;

               default:
                  /* Should never happen... but we're paranoid */
                  errorcode = SLP_ERROR_PARSE_ERROR;
                  break;
            }
         }
         else
            SLPDLogParseWarning(peerinfo, recvbuf);

       /*If there was a send list, prune the xid, since the request has been processed*/
       if(psendlist)
       {
          SLPHeader bufhead;
          SLPBuffer pnext;
          SLPBuffer pbuf = (SLPBuffer) psendlist->head;

          while(pbuf)
          {
            pnext = (SLPBuffer) pbuf->listitem.next;

            if((0 == SLPMessageParseHeader(pbuf, &bufhead)) && (bufhead.xid == header.xid))
               SLPBufferFree((SLPBuffer)SLPListUnlink(psendlist, (SLPListItem*)pbuf));
            else 
               pbuf->curpos = pbuf->start;  /*We parsed the buffer enough to attempt the xid check, we need to reset it for the next parse*/

            pbuf = pnext;
          }
       }

         if (header.functionid == SLP_FUNCT_SRVREG 
               || header.functionid == SLP_FUNCT_DAADVERT)
         {
            /* TRICKY: If this is a reg or daadvert message we do not free 
             * the message descriptor or duplicated recvbuf because they are 
             * being kept in the database!
             */
            if (errorcode == 0)
               goto FINISHED;

            /* TRICKY: If there is an error we need to free the 
             * duplicated recvbuf
             */
            SLPBufferFree(recvbuf);                    
         }
         SLPMessageFree(message);
      }
      else
         errorcode = SLP_ERROR_INTERNAL_ERROR;  /* out of memory */
   }
   else
      SLPDLogParseWarning(peerinfo,recvbuf);

FINISHED:

#ifdef DEBUG
   if (errorcode)
      SLPDLog("\n*** DEBUG *** errorcode %i during processing "
            "of message from %s\n", errorcode, SLPNetSockAddrStorageToString(
            peerinfo, addr_str, sizeof(addr_str)));
#endif

   /* Log message silently ignored because of an error */
   if (errorcode)
      if (*sendbuf == 0 || (*sendbuf)->end == (*sendbuf)->start)
         SLPDLogMessage(SLPDLOG_TRACEDROP,peerinfo,localaddr,recvbuf);

   /* Log trace message */
   SLPDLogMessage(SLPDLOG_TRACEMSG_OUT, peerinfo, localaddr, *sendbuf);

   return errorcode;
}                
Example #12
0
/*-------------------------------------------------------------------------*/
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;
}
Example #13
0
/*=========================================================================*/
int SLPDProcessMessage(struct sockaddr_in* peerinfo,
                       SLPBuffer recvbuf,
                       SLPBuffer* sendbuf)
/* Processes the recvbuf and places the results in sendbuf                 */
/*                                                                         */
/* recvfd   - the socket the message was received on                       */
/*                                                                         */
/* recvbuf  - message to process                                           */
/*                                                                         */
/* sendbuf  - results of the processed message                             */
/*                                                                         */
/* Returns  - zero on success SLP_ERROR_PARSE_ERROR or                     */
/*            SLP_ERROR_INTERNAL_ERROR on ENOMEM.                          */
/*=========================================================================*/
{
    SLPMessage  message   = 0;
    int         errorcode  = 0;

    message = SLPMessageAlloc();
    if(message == 0)
    {
        return SLP_ERROR_INTERNAL_ERROR;
    }

    errorcode = SLPMessageParseBuffer(recvbuf, message);

#if defined(ENABLE_SLPv1)
    if(message->header.version == 1)
        return SLPDv1ProcessMessage(peerinfo, recvbuf, sendbuf,
                                    message, errorcode);
#endif




    /* Log trace message */
    SLPDLogTraceMsg("IN",peerinfo,recvbuf);

    switch(message->header.functionid)
    {
    case SLP_FUNCT_SRVRQST:
        errorcode = ProcessSrvRqst(peerinfo, message, sendbuf, errorcode);
        break;

    case SLP_FUNCT_SRVREG:
        errorcode = ProcessSrvReg(peerinfo, message,sendbuf, errorcode);
        if(errorcode == 0)
        {
            SLPDKnownDAEcho(peerinfo, message, recvbuf);
        }
        break;

    case SLP_FUNCT_SRVDEREG:
        errorcode = ProcessSrvDeReg(peerinfo, message,sendbuf, errorcode);
        if(errorcode == 0)
        {
            SLPDKnownDAEcho(peerinfo, message, recvbuf);
        }
        break;

    case SLP_FUNCT_SRVACK:
        errorcode = ProcessSrvAck(peerinfo, message,sendbuf, errorcode);        
        break;

    case SLP_FUNCT_ATTRRQST:
        errorcode = ProcessAttrRqst(peerinfo, message,sendbuf, errorcode);
        break;

    case SLP_FUNCT_DAADVERT:
        errorcode = ProcessDAAdvert(peerinfo, message, sendbuf, errorcode);
        /* If necessary log that we received a DAAdvert */
        SLPDLogDATrafficMsg("IN", peerinfo, message);
        break;

    case SLP_FUNCT_SRVTYPERQST:
        errorcode = ProcessSrvTypeRqst(peerinfo, message, sendbuf, errorcode);
        break;

    case SLP_FUNCT_SAADVERT:
        errorcode = ProcessSAAdvert(peerinfo, message, sendbuf, errorcode);
        break;

    default:
        /* This may happen on a really early parse error or version not */
        /* supported error */

        /* TODO log errorcode here */

        break;
    }

    /* Log traceMsg of message was received and the one that will be sent */
    SLPDLogTraceMsg("OUT",peerinfo,*sendbuf);

    SLPMessageFree(message);

    /* Log reception of important errors */
    switch(errorcode)
    {
    case SLP_ERROR_DA_BUSY_NOW:
        SLPLog("DA_BUSY from %s\n",
               inet_ntoa(peerinfo->sin_addr));
        break;
    case SLP_ERROR_INTERNAL_ERROR:
        SLPLog("INTERNAL_ERROR from %s\n",
               inet_ntoa(peerinfo->sin_addr));
        break;
    case SLP_ERROR_PARSE_ERROR:
        SLPLog("PARSE_ERROR from %s\n",
               inet_ntoa(peerinfo->sin_addr));
        break;
    case SLP_ERROR_VER_NOT_SUPPORTED:
        SLPLog("VER_NOT_SUPPORTED from %s\n",
               inet_ntoa(peerinfo->sin_addr));
        break;                    
    }

    return errorcode;
}                
Example #14
0
/*-------------------------------------------------------------------------*/
SLPBoolean ProcessAttrRplyCallback(SLPError errorcode,
                                   struct sockaddr_in* peerinfo,
                                   SLPBuffer replybuf,
                                   void* cookie)
/*-------------------------------------------------------------------------*/
{
    SLPMessage      replymsg;
    SLPAttrRply*    attrrply;
    PSLPHandleInfo  handle      = (PSLPHandleInfo) cookie;
    SLPBoolean      result      = SLP_TRUE;

#ifdef ENABLE_SLPv2_SECURITY
    int             securityenabled;
    securityenabled = SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"));
#endif

    /*-------------------------------------------*/
    /* Check the errorcode and bail if it is set */
    /*-------------------------------------------*/
    if(errorcode)
    {
        handle->params.findattrs.callback((SLPHandle)handle,
                                          0,
                                          errorcode,
                                          handle->params.findattrs.cookie);
        return SLP_FALSE;
    }

    /*--------------------*/
    /* Parse the replybuf */
    /*--------------------*/
    replymsg = SLPMessageAlloc();
    if(replymsg)
    {
        if(SLPMessageParseBuffer(peerinfo,replybuf,replymsg) == 0 &&
                replymsg->header.functionid == SLP_FUNCT_ATTRRPLY &&
                replymsg->body.attrrply.errorcode == 0)
        {
            attrrply = &(replymsg->body.attrrply);

            if(attrrply->attrlistlen)
            {

#ifdef ENABLE_SLPv2_SECURITY
                /*-------------------------------*/
                /* Validate the authblocks       */
                /*-------------------------------*/
                if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled")) &&
                        SLPAuthVerifyString(handle->hspi,
                                            1,
                                            attrrply->attrlistlen,
                                            attrrply->attrlist,
                                            attrrply->authcount,
                                            attrrply->autharray))
                {
                    /* Could not verify the attr auth block */
                    SLPMessageFree(replymsg);
                    return result;
                }
#endif
                /*---------------------------------------*/
                /* Send the attribute list to the caller */
                /*---------------------------------------*/
                /* TRICKY: null terminate the attrlist by setting the authcount to 0 */
                ((char*)(attrrply->attrlist))[attrrply->attrlistlen] = 0;

                /* Call the callback function */
                result = handle->params.findattrs.callback((SLPHandle)handle,
                         attrrply->attrlist,
                         attrrply->errorcode * -1,
                         handle->params.findattrs.cookie);
            }
        }

        SLPMessageFree(replymsg);
    }

    return result;
}
Example #15
0
/*=========================================================================*/
int SLPDv1ProcessMessage(struct sockaddr_in* peeraddr,
                         SLPBuffer recvbuf,
                         SLPBuffer* sendbuf)
/* Processes the SLPv1 message and places the results in sendbuf           */
/*                                                                         */
/* peeraddr - the socket the message was received on                       */
/*                                                                         */
/* recvbuf  - message to process                                           */
/*                                                                         */
/* sendbuf  - results of the processed message                             */
/*                                                                         */
/* Returns  - zero on success SLP_ERROR_PARSE_ERROR or                     */
/*            SLP_ERROR_INTERNAL_ERROR on ENOMEM.                          */
/*=========================================================================*/
{
    SLPHeader   header;
    SLPMessage  message;
    int         errorcode   = 0;

    if (!G_SlpdProperty.isDA)
    {
        /* SLPv1 messages are handled only by DAs */
        errorcode = SLP_ERROR_VER_NOT_SUPPORTED;
    }

    /* Parse just the message header the reset the buffer "curpos" pointer */
    recvbuf->curpos = recvbuf->start;
    errorcode = SLPv1MessageParseHeader(recvbuf, &header);

    /* TRICKY: Duplicate SRVREG recvbufs *before* parsing them   */
    /*         it because we are going to keep them in the       */
    if (header.functionid == SLP_FUNCT_SRVREG)
    {
        recvbuf = SLPBufferDup(recvbuf);
        if (recvbuf == NULL)
        {
            return SLP_ERROR_INTERNAL_ERROR;
        }
    }

    /* Allocate the message descriptor */
    message = SLPMessageAlloc();
    if (message)
    {
        /* Parse the message and fill out the message descriptor */
        errorcode = SLPv1MessageParseBuffer(peeraddr,recvbuf, message);
        if (errorcode == 0)
        {
            /* Process messages based on type */
            switch (message->header.functionid)
            {
            case SLP_FUNCT_SRVRQST:
                errorcode = v1ProcessSrvRqst(peeraddr, message, sendbuf, errorcode);
                break;

            case SLP_FUNCT_SRVREG:
                errorcode = v1ProcessSrvReg(peeraddr,
                                            message,
                                            recvbuf,
                                            sendbuf,
                                            errorcode);
                if (errorcode == 0)
                {
                    SLPDKnownDAEcho(message, recvbuf);      
                }
                break;

            case SLP_FUNCT_SRVDEREG:
                errorcode = v1ProcessSrvDeReg(peeraddr, message, sendbuf, errorcode);
                if (errorcode == 0)
                {
                    SLPDKnownDAEcho(message, recvbuf);      
                }
                break;

            case SLP_FUNCT_ATTRRQST:
                errorcode = v1ProcessAttrRqst(peeraddr, message, sendbuf, errorcode);
                break;

            case SLP_FUNCT_SRVTYPERQST:
                errorcode = v1ProcessSrvTypeRqst(peeraddr, message, sendbuf, errorcode);
                break;

            case SLP_FUNCT_DAADVERT:
                /* we are a SLPv2 DA, ignore other v1 DAs */
                (*sendbuf)->end = (*sendbuf)->start;
                break;

            default:
                /* Should never happen... but we're paranoid */
                errorcode = SLP_ERROR_PARSE_ERROR;
                break;
            }   
        }

        if (header.functionid == SLP_FUNCT_SRVREG)
        {
            /* TRICKY: Do not free the message descriptor for SRVREGs */
            /*         because we are keeping them in the database    */
            /*         unless there is an error then we free memory   */
            if (errorcode)
            {
                SLPMessageFree(message);
                SLPBufferFree(recvbuf);
            }
        }
        else
        {
            SLPMessageFree(message);
        }
    }
    else
    {
        /* out of memory */
        errorcode = SLP_ERROR_INTERNAL_ERROR;
    }

    return errorcode;
}                
Example #16
0
/*=========================================================================*/ 
SLPError NetworkRqstRply(int sock,
                         struct sockaddr_in* destaddr,
                         const char* langtag,
                         char* buf,
                         char buftype,
                         int bufsize,
                         NetworkRqstRplyCallback callback,
                         void * cookie)
/* Transmits and receives SLP messages via multicast convergence algorithm */
/*                                                                         */
/* Returns  -    SLP_OK on success                                         */
/*=========================================================================*/ 
{
    struct timeval      timeout;
    struct sockaddr_in  peeraddr;
    SLPBuffer           sendbuf         = 0;
    SLPBuffer           recvbuf         = 0;
    SLPMessage          msg             = 0;
    SLPError            result          = 0;
#ifdef WIN32 /* on WIN32 setsockopt takes a const char * argument */
    char                socktype        = 0;
#else
    int                 socktype        = 0;
#endif
    int                 langtaglen      = 0;
    int                 prlistlen       = 0;
    char*               prlist          = 0;
    int                 xid             = 0;
    int                 mtu             = 0;
    int                 size            = 0;
    int                 xmitcount       = 0;
    int                 rplycount       = 0;
    int                 maxwait         = 0;
    int                 totaltimeout    = 0;
    int                 timeouts[MAX_RETRANSMITS];

    /*----------------------------------------------------*/
    /* Save off a few things we don't want to recalculate */
    /*----------------------------------------------------*/
    langtaglen = strlen(langtag);
    xid = SLPXidGenerate();
    mtu = SLPPropertyAsInteger(SLPGetProperty("net.slp.MTU"));
    sendbuf = SLPBufferAlloc(mtu);
    if(sendbuf == 0)
    {                 
        result = SLP_MEMORY_ALLOC_FAILED;
        goto CLEANUP;
    }

    if(buftype == SLP_FUNCT_DASRVRQST)
    {
        /* do something special for SRVRQST that will be discovering DAs */
        maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait"));
        SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.DADiscovertTimeouts"),
                                   timeouts,
                                   MAX_RETRANSMITS );
        /* SLP_FUNCT_DASRVRQST is a fake function.  We really want to */
        /* send a SRVRQST                                             */
        buftype = SLP_FUNCT_SRVRQST;
    }
     
    /* Figure unicast/multicast,TCP/UDP, wait and time out stuff */
    if(ntohl(destaddr->sin_addr.s_addr) > 0xe0000000)
    {
        /* Multicast or broadcast */
        maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.multicastMaximumWait"));
        SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.multicastTimeouts"), 
                                   timeouts, 
                                   MAX_RETRANSMITS );
        socktype = SOCK_DGRAM;
        xmitcount = 0;
    }
    else
    {
        maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.unicastMaximumWait"));
        SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.unicastTimeouts"), 
                                   timeouts, 
                                   MAX_RETRANSMITS );
        size = sizeof(socktype);
        getsockopt(sock,SOL_SOCKET,SO_TYPE,&socktype,&size);
        socktype = SOCK_STREAM;
        xmitcount = MAX_RETRANSMITS;
    }
    
    
    
    /*--------------------------------*/
    /* Allocate memory for the prlist */
    /*--------------------------------*/
    prlist = (char*)malloc(mtu);
    if(prlist == 0)
    {
        result = SLP_MEMORY_ALLOC_FAILED;
        goto CLEANUP;
    }
    *prlist = 0;
    prlistlen = 0;
    
    /*--------------------------*/
    /* Main retransmission loop */
    /*--------------------------*/
    while(xmitcount <= MAX_RETRANSMITS)
    {
        xmitcount++;

        /*--------------------*/
        /* setup recv timeout */
        /*--------------------*/
        if(socktype == SOCK_DGRAM)
        {   
            totaltimeout += timeouts[xmitcount];
            if(totaltimeout >= maxwait || timeouts[xmitcount] == 0)
            {
                /* we are all done */
                break;
            }
            timeout.tv_sec = timeouts[xmitcount] / 1000;
            timeout.tv_usec = (timeouts[xmitcount] % 1000) * 1000;
        }
        else
        {
            timeout.tv_sec = maxwait / 1000;
            timeout.tv_usec = (maxwait % 1000) * 1000;
        }
        
        size = 14 + langtaglen + 2 + prlistlen + bufsize;
        if(SLPBufferRealloc(sendbuf,size) == 0)
        {
            result = SLP_MEMORY_ALLOC_FAILED;
            goto CLEANUP;
        }

        /*-----------------------------------*/
        /* Add the header to the send buffer */
        /*-----------------------------------*/
        /*version*/
        *(sendbuf->start)       = 2;
        /*function id*/
        *(sendbuf->start + 1)   = buftype;
        /*length*/
        ToUINT24(sendbuf->start + 2, size);
        /*flags*/
        ToUINT16(sendbuf->start + 5, socktype == SOCK_STREAM ? 0 : SLP_FLAG_MCAST);
        /*ext offset*/
        ToUINT24(sendbuf->start + 7,0);
        /*xid*/
        ToUINT16(sendbuf->start + 10,xid);
        /*lang tag len*/
        ToUINT16(sendbuf->start + 12,langtaglen);
        /*lang tag*/
        memcpy(sendbuf->start + 14, langtag, langtaglen);
        sendbuf->curpos = sendbuf->start + langtaglen + 14 ;

        /*-----------------------------------*/
        /* Add the prlist to the send buffer */
        /*-----------------------------------*/
        if( buftype == SLP_FUNCT_SRVRQST ||
            buftype == SLP_FUNCT_ATTRRQST ||
            buftype == SLP_FUNCT_SRVTYPERQST)
        {
            ToUINT16(sendbuf->curpos,prlistlen);
            sendbuf->curpos = sendbuf->curpos + 2;
            memcpy(sendbuf->curpos, prlist, prlistlen);
            sendbuf->curpos = sendbuf->curpos + prlistlen;
        }
         
        /*-----------------------------*/
        /* Add the rest of the message */
        /*-----------------------------*/
        memcpy(sendbuf->curpos, buf, bufsize);
        
        /*----------------------*/
        /* send the send buffer */
        /*----------------------*/
        result = SLPNetworkSendMessage(sock,
                                       sendbuf,
                                       destaddr,
                                       &timeout);
        if(result != 0)
        {
            /* we could not send the message for some reason */
            /* we're done */
            result = SLP_NETWORK_ERROR;
            goto FINISHED;
        }
            
 
        /*----------------*/
        /* Main recv loop */
        /*----------------*/
        while(1)
        {
            
            if(SLPNetworkRecvMessage(sock,
                                     &recvbuf,
                                     &peeraddr,
                                     &timeout) != 0)
            {
                /* An error occured while receiving the message */
                /* probably a just time out error. Retry send.  */
                break;
            }
             
            /* Parse the message and call callback */
            msg = SLPMessageRealloc(msg);
            if(msg == 0)
            {
                result = SLP_MEMORY_ALLOC_FAILED;
                goto FINISHED;
            }

            if(SLPMessageParseBuffer(recvbuf, msg) == 0)
            {
                if (msg->header.xid == xid)
                {
                    rplycount = rplycount + 1;
                    if(callback(result, msg, cookie) == 0)
                    {
                        goto CLEANUP;
                    }
                }
            }
            
            if(socktype == SOCK_STREAM)
            {
                goto FINISHED;
            }

            /* add the peer to the previous responder list */
            if(prlistlen != 0)
            {
                strcat(prlist,",");
            }
            strcat(prlist,inet_ntoa(peeraddr.sin_addr));
            prlistlen =  strlen(prlist); 
        }
    }

    FINISHED:
    /*----------------*/
    /* We're all done */
    /*----------------*/
    if(rplycount == 0)
    {
        result = SLP_NETWORK_TIMED_OUT;
    }

    /*-------------------------------------*/
    /* Notify the callback that we're done */
    /*-------------------------------------*/
    callback(SLP_LAST_CALL,msg,cookie);
    
    /*----------------*/
    /* Free resources */
    /*----------------*/
    CLEANUP:
    if(prlist) free(prlist);
    SLPBufferFree(sendbuf);
    SLPBufferFree(recvbuf);
    SLPMessageFree(msg);
    close(sock);

    return result;
}