Esempio n. 1
0
/** Process a SrvTypeRequest 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 ProcessSrvTypeRqst(SLPMessage * message, SLPBuffer * sendbuf,
      int errorcode)
{
   size_t size = 0;
   SLPDDatabaseSrvTypeRqstResult * db = 0;
   SLPBuffer result = *sendbuf;

   /* If errorcode is set, we can not be sure that message is good
      Go directly to send response code                            
    */
   if (errorcode)
      goto RESPOND;

   /* check for one of our IP addresses in the prlist */
   if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen, 
         message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen,
         G_SlpdProperty.interfaces))
   {
      /* Silently ignore */
      result->end = result->start;
      goto FINISHED;  
   }

   /* make sure that we handle the scope */
   if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen,
         message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen,
         G_SlpdProperty.useScopes) != 0)
      errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db);
   else
      errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;

RESPOND:

   /* do not send error codes or empty replies to multicast requests */
   if (errorcode != 0 || db->srvtypelistlen == 0)
      if (message->header.flags & SLP_FLAG_MCAST 
            || SLPNetIsMCast(&(message->peer)))
      {
         result->end = result->start;
         goto FINISHED;  
      }

   /* ensure the buffer is big enough to handle the whole srvtyperply */
   size = message->header.langtaglen + 18;   /* 14 bytes for header     */
                                             /*  2 bytes for error code */
                                             /*  2 bytes for srvtype len */
   if (errorcode == 0)
      size += db->srvtypelistlen;

   /* Reallocate the result buffer */
   result = SLPBufferRealloc(result, size);
   if (result == 0)
   {
      errorcode = SLP_ERROR_INTERNAL_ERROR;
      goto FINISHED;
   }

   /* Add the header */

   /* version */
   *result->curpos++ = 2;

   /* function id */
   *result->curpos++ = SLP_FUNCT_SRVTYPERPLY;

   /* length */
   PutUINT24(&result->curpos, size);

   /* flags */
   PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU?
         SLP_FLAG_OVERFLOW: 0));

   /* ext offset */
   PutUINT24(&result->curpos, 0);

   /* xid */
   PutUINT16(&result->curpos, message->header.xid);

   /* lang tag len */
   PutUINT16(&result->curpos, message->header.langtaglen);

   /* lang tag */
   memcpy(result->curpos, message->header.langtag,
         message->header.langtaglen);
   result->curpos += message->header.langtaglen;

   /* Add rest of the SrvTypeRply */

   /* error code*/
   PutUINT16(&result->curpos, errorcode);
   if (errorcode == 0)
   {
      /* length of srvtype-list */
      PutUINT16(&result->curpos, db->srvtypelistlen);
      memcpy(result->curpos, db->srvtypelist, db->srvtypelistlen);
      result->curpos += db->srvtypelistlen;
   }

FINISHED:   

   if (db) 
      SLPDDatabaseSrvTypeRqstEnd(db);

   *sendbuf = result;

   return errorcode;
}
Esempio n. 2
0
/*-------------------------------------------------------------------------*/
int v1ProcessSrvTypeRqst(struct sockaddr_in* peeraddr,
                         SLPMessage message,
                         SLPBuffer* sendbuf,
                         int errorcode)
/*-------------------------------------------------------------------------*/
{
    char*                           type;
    char*                           end;
    char*                           slider;
    int                             i;
    int                             typelen;
    int                             numsrvtypes = 0;
    int                             size        = 0;
    SLPDDatabaseSrvTypeRqstResult*  db          = 0;
    SLPBuffer                       result      = *sendbuf;


    /*-------------------------------------------------*/
    /* Check for one of our IP addresses in the prlist */
    /*-------------------------------------------------*/
    if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen,
                               message->body.srvtyperqst.prlist,
                               G_SlpdProperty.interfacesLen,
                               G_SlpdProperty.interfaces))
    {
        result->end = result->start;
        goto FINISHED;
    }

    /*------------------------------------*/
    /* Make sure that we handle the scope */
    /*------------------------------------*/
    if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen,
                               message->body.srvtyperqst.scopelist,
                               G_SlpdProperty.useScopesLen,
                               G_SlpdProperty.useScopes) != 0)
    {
        /*------------------------------------*/
        /* Find service types in the database */
        /*------------------------------------*/
        errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db);
    }
    else
    {
        errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
    }

    /*----------------------------------------------------------------*/
    /* Do not send error codes or empty replies to multicast requests */
    /*----------------------------------------------------------------*/
    if (message->header.flags & SLP_FLAG_MCAST)
    {
        if (errorcode != 0 || db->srvtypelistlen == 0)
        {
            result->end = result->start;
            goto FINISHED;  
        }
    }


    /*-----------------------------------------------------------------*/
    /* ensure the buffer is big enough to handle the whole srvtyperply */
    /*-----------------------------------------------------------------*/
    size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes
                  for num of service types */
    if (errorcode == 0)
    {
        if (db->srvtypelistlen)
        {
            /* there has to be at least one service type*/
            numsrvtypes = 1;

            /* count the rest of the service types */
            type = db->srvtypelist;
            for (i=0; i< db->srvtypelistlen; i++)
            {
                if (type[i] == ',')
                {
                    numsrvtypes += 1;
                }
            }

            /* figure out how much memory is required for srvtype strings */
            typelen = INT_MAX;
            errorcode = SLPv1ToEncoding(0,
                                        &typelen,
                                        message->header.encoding,  
                                        db->srvtypelist,
                                        db->srvtypelistlen);

            /* TRICKY: we add in the numofsrvtypes + 1 to make room for the */
            /* type length.  We can do this because the ',' of the comma    */
            /* delimited list is one byte.                                  */
            size = size + typelen + numsrvtypes + 1;
        }
        else
        {
            numsrvtypes = 0;
        }
    }

    /*-----------------*/
    /* Allocate memory */
    /*-----------------*/
    result = SLPBufferRealloc(result,size);
    if (result == 0)
    {
        errorcode = SLP_ERROR_INTERNAL_ERROR;
        goto FINISHED;
    }

    /*----------------*/
    /* Add the header */
    /*----------------*/
    /*version*/
    *(result->start)       = 1;
    /*function id*/
    *(result->start + 1)   = SLP_FUNCT_SRVTYPERPLY;
    /*length*/
    ToUINT16(result->start + 2, size);
    /*flags - TODO set the flags correctly */
    *(result->start + 4) = message->header.flags |
                           (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0);  
    /*dialect*/
    *(result->start + 5) = 0;
    /*language code*/
    memcpy(result->start + 6, message->header.langtag, 2);
    ToUINT16(result->start + 8, message->header.encoding);
    /*xid*/
    ToUINT16(result->start + 10, message->header.xid);

    /*-----------------------------*/
    /* Add rest of the SrvTypeRply */
    /*-----------------------------*/
    result->curpos = result->start + 12;
    /* error code*/
    ToUINT16(result->curpos, errorcode);
    result->curpos += 2;
    if (errorcode == 0)
    {
        /* num of service types */
        ToUINT16(result->curpos, numsrvtypes);
        result->curpos += 2;

        /* service type strings */
        type = db->srvtypelist;
        slider = db->srvtypelist;
        end = &(type[db->srvtypelistlen]);
        for (i=0;i<numsrvtypes; i++)
        {
            while (slider < end && *slider != ',') slider++;

            typelen = size;
            /* put in the encoded service type */
            SLPv1ToEncoding(result->curpos + 2, 
                            &typelen,
                            message->header.encoding,
                            type,
                            slider - type);
            /* slip in the typelen */
            ToUINT16(result->curpos, typelen);
            result->curpos += 2;
            result->curpos += typelen;

            slider ++; /* skip comma */
            type = slider;
        }

        /* TODO - make sure we don't return generic types */
    }

    FINISHED:   
    if (db) SLPDDatabaseSrvTypeRqstEnd(db);

    *sendbuf = result;

    return errorcode;
}