Ejemplo n.º 1
0
/*=========================================================================*/
void SLPDSocketFree(SLPDSocket* sock)
/* Frees memory associated with the specified SLPDSocket                   */
/*                                                                         */
/* sock (IN) pointer to the socket to free                                 */
/*=========================================================================*/
{
    /* close the socket descriptor */
    CloseSocket(sock->fd);

    /* free receive buffer */
    if(sock->recvbuf)
    {
        SLPBufferFree(sock->recvbuf);
    }

    /* free send buffer(s) */
    if(sock->sendlist.count)
    {
        while(sock->sendlist.count)
        {
            SLPBufferFree((SLPBuffer)SLPListUnlink(&(sock->sendlist), sock->sendlist.head));
        }
    }
    else if(sock->sendbuf)
    {
        SLPBufferFree(sock->sendbuf);                        
    }

    /* free the actual socket structure */
    xfree(sock);
}
Ejemplo n.º 2
0
/*-------------------------------------------------------------------------*/
void HandleSocketClose(SLPDSocketList* list, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    SLPDSocketListRemove(list,sock);
    close(sock->fd);
    if(sock->recvbuf) SLPBufferFree(sock->recvbuf);
    if(sock->sendbuf) SLPBufferFree(sock->sendbuf);                        
    free(sock);
}
Ejemplo n.º 3
0
main()
{
    SLPIfaceInfo    ifaceinfo;
    SLPXcastSockets      socks;
    SLPBuffer           buffer;

    buffer = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE);
    if(buffer)
    {
        
        strcpy(buffer->start,"testdata");
    
        SLPIfaceGetInfo(NULL,&ifaceinfo);
    
        if (SLPBroadcastSend(&ifaceinfo, buffer,&socks) !=0)
            printf("\n SLPBroadcastSend failed \n");
        SLPXcastSocketsClose(&socks);
    
        if (SLPMulticastSend(&ifaceinfo, buffer, &socks) !=0)
            printf("\n SLPMulticast failed \n");
        SLPXcastSocketsClose(&socks);

        printf("Success\n");

        SLPBufferFree(buffer);
    }
}
Ejemplo n.º 4
0
int main(void)
{
   SLPIfaceInfo ifaceinfo;
   SLPIfaceInfo ifaceinfo6;
   SLPXcastSockets socks;
   SLPBuffer buffer;
   /* multicast srvloc address */
   uint8_t v6Addr[] = {0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x16};
   struct sockaddr_storage dst;
   int mtu;

#ifdef _WIN32
   WSADATA wsadata;
   WSAStartup(MAKEWORD(2, 2), &wsadata);
#endif

   mtu = SLPPropertyGetMTU();
   //const struct in6_addr in6addr;
   buffer = SLPBufferAlloc(mtu);
   if (buffer)
   {
      strcpy((char *)buffer->start, "testdata");

      SLPIfaceGetInfo(NULL,&ifaceinfo, AF_INET);
      SLPIfaceGetInfo(NULL,&ifaceinfo6, AF_INET6);

      if (SLPBroadcastSend(&ifaceinfo, buffer, &socks) !=0)
         printf("\n SLPBroadcastSend failed \n");
      SLPXcastSocketsClose(&socks);

      /* for v6 */
      if (SLPBroadcastSend(&ifaceinfo6, buffer,&socks) !=0)
         printf("\n SLPBroadcastSend failed for ipv6\n");
      SLPXcastSocketsClose(&socks);

      if (SLPMulticastSend(&ifaceinfo, buffer, &socks, 0) !=0)
         printf("\n SLPMulticast failed \n");
      SLPXcastSocketsClose(&socks);

      /* set up address and scope for v6 multicast */
      SLPNetSetAddr(&dst, AF_INET6, 0, (uint8_t *)v6Addr);
      if (SLPMulticastSend(&ifaceinfo6, buffer, &socks, &dst) !=0)
         printf("\n SLPMulticast failed for ipv\n");
      SLPXcastSocketsClose(&socks);

      printf("Success\n");

      SLPBufferFree(buffer);
   }

#ifdef _WIN32
   WSACleanup();
#endif

   return 0;
}
Ejemplo n.º 5
0
int CheckAndResizeBuffer(SLPBuffer * sendbuf, SLPBuffer tmp, size_t grow_size)
{
	int retVal = 0;

    if( (*sendbuf)->curpos + (tmp->end - tmp->start) > ( (*sendbuf)->start + (*sendbuf)->allocated) )
    {
		  /* Grow the sendbuf buffer - note that SLPBufferRealloc may potentially do a memset if the DEBUG flag is set
		     Therefore we have to copy the old contents into the buffer afterwards to be sure
		  */
#ifdef DEBUG
		  SLPBuffer duplicate = SLPBufferDup( (*sendbuf) );
#endif
		  /* store how far we are from the start of the buffer */
		  size_t currentPosFromStart = (*sendbuf)->curpos - (*sendbuf)->start;

		  /* check to make sure we're growing by at least the size of the tmp buffer */
		  *sendbuf = SLPBufferRealloc( (*sendbuf), ((*sendbuf)->allocated + ((size_t)(tmp->end - tmp->start) > grow_size?(tmp->end - tmp->start):grow_size)) );
	      if (*sendbuf == 0)
	      {
	         retVal = SLP_ERROR_INTERNAL_ERROR;
	      }
	      else
	      {
		     /* update the current position to what it was before */
		     (*sendbuf)->curpos = (*sendbuf)->start + currentPosFromStart;
#ifdef DEBUG
    		  memcpy( (*sendbuf)->start, duplicate->start, duplicate->end - duplicate->start );
#endif
	      }
#ifdef DEBUG
		  SLPBufferFree(duplicate);
		  duplicate = 0;
#endif
    }

    return retVal;
}
Ejemplo n.º 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;
}
Ejemplo n.º 7
0
/** Read service registrations from a text file.
 *
 * A really big and nasty function that reads service registrations from
 * from a file. Don't look at this too hard or you'll be sick. This is by
 * far the most horrible code in OpenSLP. Please volunteer to rewrite it!
 *
 * "THANK GOODNESS this function is only called at startup" -- Matt
 *
 * @param[in] fd - The file to read from.
 * @param[out] msg - A message describing the SrvReg in buf.
 * @param[out] buf - The buffer used to hold @p message data.
 *
 * @return Zero on success. A value greater than zero on error. A value
 *    less than zero on EOF.
 *
 * @note Eventually the caller needs to call SLPBufferFree and
 *    SLPMessageFree to free memory.
 */
int SLPDRegFileReadSrvReg(FILE * fd, SLPMessage ** msg, SLPBuffer * buf)
{
   char * slider1;
   char * slider2;
   char line[4096];

   struct sockaddr_storage peer;
   int result = 0;
   size_t bufsize = 0;
   size_t langtaglen = 0;
   char * langtag = 0;
   size_t scopelistlen = 0;
   char * scopelist = 0;
   size_t urllen = 0;
   char * url = 0;
   int lifetime = 0;
   size_t srvtypelen = 0;
   char * srvtype = 0;
   size_t attrlistlen = 0;
   char * attrlist = 0;
   SLPBuffer tmp;

#ifdef ENABLE_SLPv2_SECURITY
   unsigned char * urlauth = 0;
   int urlauthlen = 0;
   unsigned char * attrauth = 0;
   int attrauthlen = 0;
#endif

   /* give the out params an initial NULL value */
   *buf = 0;
   *msg = 0;

   /* read the next non-white non-comment line from the stream */
   do
   {
      slider1 = RegFileReadLine(fd, line, 4096);
      if (slider1 == 0)
         return -1;

   } while (*slider1 == 0x0d ||  *slider1 == 0x0a);

   /* Parse the url-props */
   slider2 = strchr(slider1, ',');
   if (slider2)
   {
      /* srvurl */
      *slider2 = 0; /* squash comma to null terminate srvurl */
      url = xstrdup(TrimWhitespace(slider1));
      if (url == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      urllen = strlen(url);

      /* derive srvtype from srvurl */
      srvtype = strstr(slider1, "://");
      if (srvtype == 0)
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }
      *srvtype = 0;
      srvtype=xstrdup(TrimWhitespace(slider1));
      if (srvtype == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      srvtypelen = strlen(srvtype);
      slider1 = slider2 + 1;

      /*lang*/
      slider2 = strchr(slider1, ',');
      if (slider2)
      {
         *slider2 = 0; /* squash comma to null terminate lang */
         langtag = xstrdup(TrimWhitespace(slider1));
         if (langtag == 0)
         {
            result = SLP_ERROR_INVALID_REGISTRATION;
            goto CLEANUP;
         }
         langtaglen = strlen(langtag);
         slider1 = slider2 + 1;
      }
      else
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }

      /* ltime */
      slider2 = strchr(slider1,',');
      if (slider2)
      {
         *slider2 = 0; /* squash comma to null terminate ltime */
         lifetime = atoi(slider1);
         slider1 = slider2 + 1;
      }
      else
      {
         lifetime = atoi(slider1);
         slider1 = slider2;
      }
      if (lifetime < 1 || lifetime > SLP_LIFETIME_MAXIMUM)
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }

      /* get the srvtype if one was not derived by the srvurl */
      if (srvtype == 0)
      {
         srvtype = xstrdup(TrimWhitespace(slider1));
         if (srvtype == 0)
         {
            result = SLP_ERROR_INTERNAL_ERROR;
            goto CLEANUP;
         }
         srvtypelen = strlen(srvtype);
         if (srvtypelen == 0)
         {
            result = SLP_ERROR_INVALID_REGISTRATION;
            goto CLEANUP;
         }
      }
   }
   else
   {
      result = SLP_ERROR_INVALID_REGISTRATION;
      goto CLEANUP;
   }

   /* read all the attributes including the scopelist */
   *line=0;
   while (1)
   {
      slider1 = RegFileReadLine(fd,line,4096);
      if (slider1 == 0)
      {
         result = -1;
         break;
      }
      if (*slider1 == 0x0d || *slider1 == 0x0a)
         break;

      /* Check to see if it is the scopes line */
      /* FIXME We can collapse the scope stuff into the value getting and
         just make it a special case (do strcmp on the tag as opposed to the
         line) of attribute getting. */
      if (strncasecmp(slider1,"scopes", 6) == 0)
      {
         /* found scopes line */
         slider2 = strchr(slider1,'=');
         if (slider2)
         {
            slider2++;
            if (*slider2)
            {
               /* just in case some idiot puts multiple scopes lines */
               if (scopelist)
               {
                  result = SLP_ERROR_SCOPE_NOT_SUPPORTED;
                  goto CLEANUP;
               }

               /* make sure there are no spaces in the scope list
      NOTE: There's nothing in the spec that indicates that
      scopes can't contain spaces. Commenting out for now. --jmc
               if (strchr(slider2, ' '))
               {
                  result = SLP_ERROR_SCOPE_NOT_SUPPORTED;
                  goto CLEANUP;
               } */

               scopelist = xstrdup(TrimWhitespace(slider2));
               if (scopelist == 0)
               {
                  result = SLP_ERROR_INTERNAL_ERROR;
                  goto CLEANUP;
               }
               scopelistlen = strlen(scopelist);
            }
         }
      }
      else
      {
         /* line contains an attribute (slow but it works)*/
         /* TODO Fix this so we do not have to realloc memory each time! */
         TrimWhitespace(slider1);

         if (attrlist == 0)
         {
            attrlistlen += strlen(slider1) + 2;
            attrlist = xmalloc(attrlistlen + 1);
            if (attrlist == 0)
            {
               result = SLP_ERROR_INTERNAL_ERROR;
               goto CLEANUP;
            }
            *attrlist = 0;
         }
         else
         {
            char * tmp_attrlist;
            attrlistlen += strlen(slider1) + 3;
            if ((tmp_attrlist = xrealloc(attrlist, attrlistlen + 1)) == 0)
            {
               xfree(attrlist);
               result = SLP_ERROR_INTERNAL_ERROR;
               goto CLEANUP;
            }
            attrlist = tmp_attrlist;
            strcat(attrlist, ",");
         }

         if (attrlist == 0)
         {
            result = SLP_ERROR_INTERNAL_ERROR;
            goto CLEANUP;
         }

         /* we need special case for keywords (why do we need these)
            they seem like a waste of code.  Why not just use booleans */
         if (strchr(slider1, '='))
         {
            /* normal attribute (with '=') */
            strcat(attrlist, "(");
            strcat(attrlist, slider1);
            strcat(attrlist, ")");
         }
         else
         {
            /* keyword (no '=') */
            attrlistlen -= 2; /* subtract 2 bytes for no '(' or ')' */
            strcat(attrlist, slider1);
         }
      }
   }

   /* Set the scope set in properties if not is set */
   if (scopelist == 0)
   {
      scopelist = xstrdup(G_SlpdProperty.useScopes);
      if (scopelist == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      scopelistlen = G_SlpdProperty.useScopesLen;
   }

#ifdef ENABLE_SLPv2_SECURITY
   /* generate authentication blocks */
   if (G_SlpdProperty.securityEnabled)
   {
      SLPAuthSignUrl(G_SlpdSpiHandle, 0, 0, urllen, url,
            &urlauthlen, &urlauth);
      SLPAuthSignString(G_SlpdSpiHandle, 0, 0, attrlistlen, attrlist,
            &attrauthlen, &attrauth);
   }
#endif

   /* allocate buffer for the SrvReg Message */
   bufsize = 14 + langtaglen;    /* 14 bytes for header    */
   bufsize += urllen + 6;        /*  1 byte for reserved   */
                                 /*  2 bytes for lifetime  */
                                 /*  2 bytes for urllen    */
                                 /*  1 byte for authcount  */
   bufsize += srvtypelen + 2;    /*  2 bytes for len field */
   bufsize += scopelistlen + 2;  /*  2 bytes for len field */
   bufsize += attrlistlen + 2;   /*  2 bytes for len field */
   bufsize += 1;                 /*  1 byte for authcount  */

#ifdef ENABLE_SLPv2_SECURITY
   bufsize += urlauthlen;
   bufsize += attrauthlen;
#endif

   tmp = *buf = SLPBufferAlloc(bufsize);
   if (tmp == 0)
   {
      result = SLP_ERROR_INTERNAL_ERROR;
      goto CLEANUP;
   }

   /* now build the SrvReg Message */

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

   /* function id */
   *tmp->curpos++ = SLP_FUNCT_SRVREG;

   /* length */
   PutUINT24(&tmp->curpos, bufsize);

   /* flags */
   PutUINT16(&tmp->curpos, 0);

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

   /* xid */
   PutUINT16(&tmp->curpos, 0);

   /* lang tag len */
   PutUINT16(&tmp->curpos, langtaglen);

   /* lang tag */
   memcpy(tmp->curpos, langtag, langtaglen);
   tmp->curpos += langtaglen;

   /* url-entry reserved */
   *tmp->curpos++ = 0;

   /* url-entry lifetime */
   PutUINT16(&tmp->curpos, lifetime);

   /* url-entry urllen */
   PutUINT16(&tmp->curpos, urllen);

   /* url-entry url */
   memcpy(tmp->curpos, url, urllen);
   tmp->curpos += urllen;

   /* url-entry authblock */
#ifdef ENABLE_SLPv2_SECURITY
   if (urlauth)
   {
      /* authcount */
      *tmp->curpos++ = 1;

      /* authblock */
      memcpy(tmp->curpos, urlauth, urlauthlen);
      tmp->curpos += urlauthlen;
   }
   else
#endif
      *tmp->curpos++ = 0;

   /* service type */
   PutUINT16(&tmp->curpos, srvtypelen);
   memcpy(tmp->curpos, srvtype, srvtypelen);
   tmp->curpos += srvtypelen;

   /* scope list */
   PutUINT16(&tmp->curpos, scopelistlen);
   memcpy(tmp->curpos, scopelist, scopelistlen);
   tmp->curpos += scopelistlen;

   /* attr list */
   PutUINT16(&tmp->curpos, attrlistlen);
   memcpy(tmp->curpos, attrlist, attrlistlen);
   tmp->curpos += attrlistlen;

   /* attribute auth block */
#ifdef ENABLE_SLPv2_SECURITY
   if (attrauth)
   {
      /* authcount */
      *tmp->curpos++ = 1;

      /* authblock */
      memcpy(tmp->curpos, attrauth, attrauthlen);
      tmp->curpos += attrauthlen;
   }
   else
#endif
      *tmp->curpos++ = 0;

   /* okay, now comes the really stupid (and lazy part) */
   *msg = SLPMessageAlloc();
   if (*msg == 0)
   {
      SLPBufferFree(*buf);
      *buf = 0;
      result = SLP_ERROR_INTERNAL_ERROR;
      goto CLEANUP;
   }

   /* this should be ok even if we are not supporting IPv4,
    * since it's a static service
    */
   memset(&peer, 0, sizeof(struct sockaddr_in));
   peer.ss_family = AF_UNSPEC;
   ((struct sockaddr_in *)&peer)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   result = SLPMessageParseBuffer(&peer, &peer, *buf, *msg);
   (*msg)->body.srvreg.source = SLP_REG_SOURCE_STATIC;

CLEANUP:

   /* check for errors and free memory */
   switch(result)
   {
      case SLP_ERROR_INTERNAL_ERROR:
         SLPDLog("\nERROR: Out of memory one reg file line:\n   %s\n", line);
         break;

      case SLP_ERROR_INVALID_REGISTRATION:
         SLPDLog("\nERROR: Invalid reg file format near:\n   %s\n", line);
         break;

      case SLP_ERROR_SCOPE_NOT_SUPPORTED:
         SLPDLog("\nERROR: Duplicate scopes or scope list with "
               "embedded spaces near:\n   %s\n", line);
         break;

      default:
         break;
   }

   xfree(langtag);
   xfree(scopelist);
   xfree(url);
   xfree(srvtype);
   xfree(attrlist);

#ifdef ENABLE_SLPv2_SECURITY
   xfree(urlauth);
   xfree(attrauth);
#endif

   return result;
}
Ejemplo n.º 8
0
/*-------------------------------------------------------------------------*/
void OutgoingStreamRead(SLPList* socklist, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    int     bytesread;
    char    peek[16];
    int     peeraddrlen = sizeof(struct sockaddr_in);

    if ( sock->state == STREAM_READ_FIRST )
    {
        /*---------------------------------------------------*/
        /* take a peek at the packet to get size information */
        /*---------------------------------------------------*/
        bytesread = recvfrom(sock->fd,
                             peek,
                             16,
                             MSG_PEEK,
                             (struct sockaddr *)&(sock->peeraddr),
                             &peeraddrlen);
        if ( bytesread > 0 )
        {
            /* allocate the recvbuf big enough for the whole message */
            sock->recvbuf = SLPBufferRealloc(sock->recvbuf,AsUINT24(peek+2));
            if ( sock->recvbuf )
            {
                sock->state = STREAM_READ;
            }
            else
            {
                SLPDLog("INTERNAL_ERROR - out of memory!\n");
                sock->state = SOCKET_CLOSE;
            }
        }
        else
        {
#ifdef WIN32
            if ( WSAEWOULDBLOCK != WSAGetLastError() )
#else
            if ( errno != EWOULDBLOCK )
#endif
            {
                /* Error occured or connection was closed. Try to reconnect */
                /* Socket will be closed if connect times out               */
                OutgoingStreamReconnect(socklist,sock);
            }
        }       
    }

    if ( sock->state == STREAM_READ )
    {
        /*------------------------------*/
        /* recv the rest of the message */
        /*------------------------------*/
        bytesread = recv(sock->fd,
                         sock->recvbuf->curpos,
                         sock->recvbuf->end - sock->recvbuf->curpos,
                         0);
        if ( bytesread > 0 )
        {
            /* reset age because of activity */
            sock->age = 0;

            /* move buffer pointers */
            sock->recvbuf->curpos += bytesread;

            /* check to see if everything was read */
            if ( sock->recvbuf->curpos == sock->recvbuf->end )
            {
                switch ( SLPDProcessMessage(&(sock->peeraddr),
                                            sock->recvbuf,
                                            &(sock->sendbuf)) )
                {
                case SLP_ERROR_DA_BUSY_NOW:
                    sock->state = STREAM_WRITE_WAIT;
                    break;
                case SLP_ERROR_PARSE_ERROR:
                case SLP_ERROR_VER_NOT_SUPPORTED:
                    sock->state = SOCKET_CLOSE;
                    break;
                default:
                    /* End of outgoing message exchange. Unlink   */
                    /* send buf from to do list and free it       */
                    SLPBufferFree((SLPBuffer)SLPListUnlink(&(sock->sendlist),(SLPListItem*)(sock->sendbuf)));
                    sock->state = STREAM_WRITE_FIRST;
                    /* clear the reconnection count since we actually
                     * transmitted a successful message exchange
                     */
                    sock->reconns = 0;
                    break;
                }
            }
        }
        else
        {
#ifdef WIN32
            if ( WSAEWOULDBLOCK != WSAGetLastError() )
#else
            if ( errno != EWOULDBLOCK )
#endif
            {
                /* Error occured or connection was closed. Try to reconnect */
                /* Socket will be closed if connect times out               */
                OutgoingStreamReconnect(socklist,sock);
            }
        }
    }
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
}                
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}                
Ejemplo n.º 14
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;
}