Exemple #1
0
/*=========================================================================*/
SLPDAEntry* SLPDKnownDAAdd(struct in_addr* addr,
                           unsigned long bootstamp,
                           const char* scopelist,
                           int scopelistlen)
/* Adds a DA to the known DA list.  If DA already exists, entry is updated */
/*                                                                         */
/* addr     (IN) pointer to in_addr of the DA to add                       */
/*                                                                         */
/* scopelist (IN) scope list of the DA to add                              */
/*                                                                         */
/* scopelistlen (IN) the length of the scope list                          */
/*                                                                         */
/* returns  Pointer to the added or updated                                */
/*=========================================================================*/
{
    SLPDAEntry* entry;

    /* Iterate through the list looking for an identical entry */
    entry = (SLPDAEntry*)G_KnownDAList.head;
    while (entry)
    {
        /* for now assume entries are the same if in_addrs match */
        if (memcmp(&entry->daaddr,addr,sizeof(struct in_addr)) == 0)
        {
            /* Update an existing entry */
            if (entry->bootstamp < bootstamp)
            {
                entry->bootstamp = bootstamp;
            }
            else
            {
                /* set bootstamp to zero so that slpd will re-register with */
                /* this DA                                                  */
                bootstamp = 0;
            }
            entry->scopelist = realloc(entry->scopelist,scopelistlen);
            if (entry->scopelist)
            {
                memcpy(entry->scopelist,scopelist,scopelistlen);
                entry->scopelistlen = scopelistlen;
            }
            else
            {
                free(entry);
                entry = 0;
            }

            return entry;
        }

        entry = (SLPDAEntry*)entry->listitem.next;
    }

    /* Create and link in a new entry */    
    bootstamp = 0;  /* make sure we re-register with new entries */
    entry = SLPDAEntryCreate(addr,bootstamp,scopelist,scopelistlen);
    SLPListLinkHead(&G_KnownDAList,(SLPListItem*)entry);

    return entry;
}
Exemple #2
0
/*=========================================================================*/
void SLPDOutgoingDatagramWrite(SLPDSocket* sock)
/* Add a ready to write outgoing datagram socket to the outgoing list.     */
/* The datagram will be written then sit in the list until it ages out     */
/* (after  net.slp.unicastMaximumWait)                                     */
/*                                                                         */
/* sock (IN) the socket that will belong on the outgoing list              */
/*=========================================================================*/
{
    if ( sendto(sock->fd,
                sock->sendbuf->start,
                sock->sendbuf->end - sock->sendbuf->start,
                0,
                (struct sockaddr *) &(sock->peeraddr),
                sizeof(struct sockaddr_in)) >= 0 )
    {
        /* Link the socket into the outgoing list so replies will be */
        /* processed                                                 */
        SLPListLinkHead(&G_OutgoingSocketList,(SLPListItem*)(sock));
    }
    else
    {
        #ifdef DEBUG
        SLPDLog("ERROR: Data could not send() in SLPDOutgoingDatagramWrite()");
        #endif
        SLPDSocketFree(sock);
    }   
}
Exemple #3
0
/*-------------------------------------------------------------------------*/
int KnownDAListAdd(SLPList* dalist, SLPDAEntry* addition)
/* Add an entry to the KnownDA cache                                       */
/*                                                                         */
/* Returns: zero if DA was already in the list. >0 if DA was new           */
/*-------------------------------------------------------------------------*/
{
    SLPDAEntry*     entry;

    entry = (SLPDAEntry*)dalist->head;
    while(entry)
    {
        if(SLPCompareString(addition->urllen,
                            addition->url,
                            entry->urllen,
                            entry->url) == 0)
        {
            /* entry already in the list */
            break;
        }

        entry = (SLPDAEntry*) entry->listitem.next;
    }

    if(entry == 0)
    {
        /* Add the entry if it does not exist */
        SLPListLinkHead(dalist,(SLPListItem*)addition);
        return 1;
    }

    /* entry already in the list */
    return 0;
}
Exemple #4
0
/*=========================================================================*/
int SLPDDatabaseInit(const char* regfile)
/* Optionaly initialize the database with registrations from a regfile.    */
/*                                                                         */
/* regfile  (IN)    the regfile to register.                               */
/*                                                                         */
/* Returns  - zero on success or non-zero on error.                        */
/*=========================================================================*/
{
    FILE*               fd;
    SLPDDatabaseEntry*  entry;

    /*--------------------------------------*/
    /* Read static registration file if any */
    /*--------------------------------------*/
    if(regfile)
    {
        fd = fopen(regfile,"rb");
        if(fd)
        {
            while(SLPDRegFileReadEntry(fd,&entry) != 0)
            {
                /* Log registration */
                SLPDLogTraceReg("Registered (static)",entry);

                SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry);
            }

            fclose(fd);
        }
    }

    return 0;
}
Exemple #5
0
/*-------------------------------------------------------------------------*/
void IncomingSocketListen(SLPList* socklist, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    SLPDSocket* connsock;
    const int   lowat = SLPD_SMALLEST_MESSAGE;
    
    /* Only accept if we can. If we still maximum number of sockets, just*/
    /* ignore the connection */
    if(socklist->count < SLPD_MAX_SOCKETS)
    {
        connsock = SLPDSocketAlloc();
        if(connsock)
        {
            connsock->peerinfo.peeraddrlen = sizeof(sock->peerinfo.peeraddr);
            connsock->fd = accept(sock->fd,
                                  &(connsock->peerinfo.peeraddr), 
                                  &(connsock->peerinfo  .peeraddrlen));
            if(connsock->fd >= 0)
            {
                setsockopt(connsock->fd,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat));
                setsockopt(connsock->fd,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); 
                connsock->peerinfo.peertype = SLPD_PEER_ACCEPTED;
                connsock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE);
                connsock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE);
                connsock->state = STREAM_READ_FIRST;
                sock->age = 0;
                SLPListLinkHead(socklist,(SLPListItem*)connsock);
            }
            else
            {
                SLPDSocketFree(connsock);
            }
        }
    }
}
Exemple #6
0
/*-------------------------------------------------------------------------*/
int SlpPerfTest1_slpreg (SLPHandle hslp,
                         SLPList* service_list,
                         double* ave_slpreg,
                         int* count_slpreg)
/*-------------------------------------------------------------------------*/
{
    struct timezone tz;
    struct timeval  start;
    struct timeval  end;
    TestService_T*  srv;
    SLPError        errorcode;
        
    srv = CreateRandomTestService(*count_slpreg);
    if(srv == 0)
    {
        return ENOMEM;
    }

    
    /* mark start time */
    gettimeofday(&start,&tz);
    
    /* call SLP API */
    errorcode = SLPReg(hslp,
                       srv->serviceurl,
                       SLP_LIFETIME_MAXIMUM - 1,
                       srv->servicetype,
                       srv->attributes,
                       SLP_TRUE,
                       SlpPerfTest1_regreport,
                       srv);
    if(errorcode != SLP_OK)
    {
        printf("SLPReg(hslp,%s,SLP_LIFETIME_MAX,%s,%s,SLP_FALSE,callback,0) returned %i\n",
               srv->serviceurl,
               srv->servicetype,
               srv->attributes,
               errorcode);
        
        printf("This should not happen!\n");
        
        return -1;
    }
    /* mark end time */
    gettimeofday(&end,&tz);
    
    /* link the registered service into the list */
    SLPListLinkHead(service_list,(SLPListItem*)srv);

    /* recalculate average time */
    *ave_slpreg = (*ave_slpreg) * (*count_slpreg) + ElapsedTime(&start,&end);
    *count_slpreg = *count_slpreg + 1;
    *ave_slpreg = *ave_slpreg / *count_slpreg;

    return 0;
}
Exemple #7
0
/** Set a new value for a property by name.
 * 
 * If the value is NULL or empty, then simply erase the existing value and
 * return.
 *
 * @param[in] name - The name of the desired property.
 * @param[in] value - The new value to which @p name should be set or
 *    NULL if the existing value should be removed.
 * @param[in] attrs - The attributes of this property - zero means no
 *    attributes are assigned, other values include SLP_PA_USERSET and 
 *    SLP_PA_READONLY.
 *
 * @return Zero on success; -1 on error, with errno set.
 * 
 * @remarks The @p attrs parameter contains a set of bit flags indicating
 * various attributes of the property. These attributes control write 
 * permissions mostly. SLP_PA_USERSET means that an attribute may not
 * be changed by reading a configuration file, except in a complete 
 * re-initialization scenario. SLP_PA_READONLY sounds like the same thing, 
 * but it's not. The difference is that once set, properties with the 
 * SLP_PA_READONLY attribute may NEVER be reset (again, except in a complete 
 * re-initialization scenario), while properties with the SLP_PA_USERSET 
 * attribute may only be reset by passing this same flag in @p attrs, 
 * indicating that the caller is actually a user, and so has the right
 * to reset the property value.
 */
int SLPPropertySet(char const * name, char const * value, unsigned attrs)
{
   size_t namesz, valuesz;
   SLPProperty * oldprop;
   SLPProperty * newprop = 0;    /* we may be just removing the old */
   bool update = true;           /* reset if old property exists */

   /* property names must not be null or empty */
   SLP_ASSERT(name && *name);
   if (!name || !*name)
      return -1;

   if (value)
   {
      /* allocate property entry for this new value */
      namesz = strlen(name) + 1;
      valuesz = strlen(value) + 1;
      if ((newprop = (SLPProperty*)xmalloc(
            sizeof(SLPProperty) - 1 + namesz + valuesz)) == 0)
      {
         errno = ENOMEM;
         return -1;
      }

      /* set internal pointers to trailing buffer space, copy values */
      newprop->attrs = attrs;
      memcpy(newprop->name, name, namesz);
      newprop->value = newprop->name + namesz;
      memcpy(newprop->value, value, valuesz);
   }

   SLPMutexAcquire(s_PropDbLock);

   /* locate and possibly remove old property */
   if ((oldprop = Find(name))!= 0)
   {
      /* update ONLY if old is clean, or new and old are user-settable . */
      update = !oldprop->attrs 
            || (oldprop->attrs == SLP_PA_USERSET && attrs == SLP_PA_USERSET);
      if (update)
         SLPListUnlink(&s_PropertyList, (SLPListItem *)oldprop);
   }

   /* link in new property, if specified and old property was removed */
   if (newprop && update)
      SLPListLinkHead(&s_PropertyList, (SLPListItem *)newprop);

   SLPMutexRelease(s_PropDbLock);

   /* if old property was not removed, delete the new one instead */
   xfree(update? oldprop: newprop);

   return update? 0: ((errno = EACCES), -1);
}
Exemple #8
0
/*=========================================================================*/
int SLPDDatabaseInit(const char* regfile)
/* Optionaly initialize the database with registrations from a regfile.    */
/*                                                                         */
/* regfile  (IN)    the regfile to register.                               */
/*                                                                         */
/* Returns  - zero on success or non-zero on error.                        */
/*=========================================================================*/
{
    FILE*               fd;
#ifdef WIN32
    int                 mypid = GetCurrentProcessId();
    int                 myuid = 0; /* TODO: find an equivalent to 
                                      uid on Win32 */
#else
    int                 mypid = getpid();
    int                 myuid = getuid();
#endif
    SLPDDatabaseEntry*  entry;

    /* Remove all entries in the database if any */
    FreeAllEntries(&G_DatabaseList);

    /*--------------------------------------*/
    /* Read static registration file if any */
    /*--------------------------------------*/
    if(regfile)
    {
        fd = fopen(regfile,"rb");
        if(fd)
        {
            
            SLPLog("Reading registration file %s\n",regfile);

            while(SLPDRegFileReadEntry(fd,&entry) != 0)
            {
                entry->pid              = mypid;
                entry->uid              = myuid;

                if(G_SlpdProperty.traceReg)
                {
                    SLPDLogTraceReg("SrvReg (static)",entry);
                }

                SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry);
            }

            fclose(fd);
        }
    }
    
    return 0;
}
Exemple #9
0
/*-------------------------------------------------------------------------*/
void IncomingSocketListen(SLPList* socklist, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    int                 fdflags;
    sockfd_t            fd;
    SLPDSocket*         connsock;
    struct sockaddr_in  peeraddr;
    socklen_t           peeraddrlen;
#ifdef WIN32
    const char   lowat = SLPD_SMALLEST_MESSAGE;
#else    
    const int   lowat = SLPD_SMALLEST_MESSAGE;
#endif


    /* Only accept if we can. If we still maximum number of sockets, just*/
    /* ignore the connection */
    if (socklist->count < SLPD_MAX_SOCKETS)
    {
        peeraddrlen = sizeof(peeraddr);
        fd = accept(sock->fd,
                    (struct sockaddr *) &peeraddr, 
                    &peeraddrlen);
        if (fd >= 0)
        {
            connsock = SLPDSocketAlloc();
            if (connsock)
            {
                /* setup the accepted socket */
                connsock->fd        = fd;
                connsock->peeraddr  = peeraddr;
                connsock->state     = STREAM_READ_FIRST;

                /* Set the low water mark on the accepted socket */
                setsockopt(connsock->fd,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat));
                setsockopt(connsock->fd,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); 
                /* set accepted socket to non blocking */
#ifdef WIN32
                fdflags = 1;
                ioctlsocket(connsock->fd, FIONBIO, &fdflags);
#else
                fdflags = fcntl(connsock->fd, F_GETFL, 0);
                fcntl(connsock->fd,F_SETFL, fdflags | O_NONBLOCK);
#endif        
                SLPListLinkHead(socklist,(SLPListItem*)connsock);
            }
        }
    }
}
Exemple #10
0
/*=========================================================================*/
int SLPPropertySet(const char *pcName,
                   const char *pcValue)
/*=========================================================================*/
{
    int             pcNameSize; 
    int             pcValueSize;
    SLPProperty*    newProperty; 

    if(pcValue == 0)
    {
       /* Bail for right now */
       return 0;
    }
    
    newProperty = Find(pcName);
    pcNameSize = strlen(pcName) + 1;
    pcValueSize = strlen(pcValue) + 1;

    if(newProperty == 0)
    {
        /* property does not exist in the list */
        newProperty = (SLPProperty*)xmalloc(sizeof(SLPProperty) + pcNameSize + pcValueSize);
        if(newProperty == 0)
        {
            /* out of memory */
            errno = ENOMEM;
            return -1;
        }

        /* set the pointers in the SLPProperty structure to point to areas of    */
        /* the previously allocated block of memory                              */
        newProperty->propertyName   = ((char*)newProperty) + sizeof(SLPProperty); 
        newProperty->propertyValue  = newProperty->propertyName + pcNameSize;

        /* copy the passed in name and value */
        memcpy(newProperty->propertyName,pcName,pcNameSize);
        memcpy(newProperty->propertyValue,pcValue,pcValueSize);

        /* Link the new property into the list */
        SLPListLinkHead(&G_SLPPropertyList,(SLPListItem*)newProperty);
    }
    else
    {
        SLPListUnlink(&G_SLPPropertyList,(SLPListItem*)newProperty);

        /* property already exists in the list */
        newProperty = (SLPProperty*)xrealloc(newProperty,sizeof(SLPProperty) + pcNameSize + pcValueSize);    
        if(newProperty == 0)
        {
            /* out of memory */
            errno = ENOMEM;
            return -1;
        }

        /* set the pointers in the SLPProperty structure to point to areas of    */
        /* the previously allocated block of memory                              */
        newProperty->propertyName   = ((char*)newProperty) + sizeof(SLPProperty); 
        newProperty->propertyValue  = newProperty->propertyName + pcNameSize;

        /* copy the passed in name and value */
        memcpy(newProperty->propertyName,pcName,pcNameSize);
        memcpy(newProperty->propertyValue,pcValue,pcValueSize);

        SLPListLinkHead(&G_SLPPropertyList,(SLPListItem*)newProperty);
    }

    return 0;
}
Exemple #11
0
/*=========================================================================*/
int SLPDDatabaseReg(SLPSrvReg* srvreg,
                    int fresh,
                    pid_t pid,
                    uid_t uid)
/* Add a service registration to the database                              */
/*                                                                         */
/* srvreg   -   (IN) pointer to the SLPSrvReg to be added to the database  */
/*                                                                         */
/* fresh    -   (IN) pass in nonzero if the registration is fresh.         */
/*                                                                         */
/* pid      -   (IN) process id of the process that registered the service */
/*                                                                         */
/* uid      -   (IN) user id of the user that registered the service       */
/*                                                                         */
/* Returns  -   Zero on success.  non-zero on error                        */
/*                                                                         */
/* NOTE:        All registrations are treated as fresh regardless of the   */
/*              setting of the fresh parameter                             */
/*=========================================================================*/
{
    int                result = 0;
    SLPDDatabaseEntry* entry  = (SLPDDatabaseEntry*)G_DatabaseList.head;

    /* Check to see if there is already an identical entry */
    while(entry)
    {
        if(SLPCompareString(entry->urllen,
                            entry->url,
                            srvreg->urlentry.urllen,
                            srvreg->urlentry.url) == 0)
        {
            if(SLPIntersectStringList(entry->scopelistlen,
                                      entry->scopelist,
                                      srvreg->scopelistlen,
                                      srvreg->scopelist) > 0)
            {
                SLPListUnlink(&G_DatabaseList,(SLPListItem*)entry);
                break;
            } 
        }             
        
        entry = (SLPDDatabaseEntry*) entry->listitem.next;
    }
    

    /* if no identical entry are found, create a new one */
    if(entry == 0)
    {
        entry = (SLPDDatabaseEntry*)malloc(sizeof(SLPDDatabaseEntry));
        if(entry == 0)
        {
            return -1;
        }
        memset(entry,0,sizeof(SLPDDatabaseEntry));
    }
    
    /* copy info from the message from the wire to the database entry */
    entry->pid          = pid;
    entry->uid          = uid;
    entry->scopelistlen = srvreg->scopelistlen;
    entry->scopelist    = (char*)memdup(srvreg->scopelist,srvreg->scopelistlen);
    entry->lifetime     = srvreg->urlentry.lifetime;
    entry->urllen       = srvreg->urlentry.urllen;
    entry->url          = (char*)memdup(srvreg->urlentry.url, srvreg->urlentry.urllen);
    entry->srvtypelen   = srvreg->srvtypelen;
    entry->srvtype      = (char*)memdup(srvreg->srvtype,srvreg->srvtypelen);
    entry->attrlistlen  = srvreg->attrlistlen;
    if (entry->attrlistlen)
	entry->attrlist = (char*)memdup(srvreg->attrlist,srvreg->attrlistlen);
    
    /* check for malloc() failures */
    if(entry->scopelist == 0 ||
       entry->url == 0 ||
       entry->srvtype == 0 ||
       (entry->attrlistlen && entry->attrlist == 0))
    {
        FreeEntry(entry);
        return -1;
    }
    
    /* link the new (or modified) entry into the list */
    SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry);

    /* traceReg if necessary */
    if(G_SlpdProperty.traceReg)
    {
        SLPDLogTraceReg("SrvReg", entry);
    }

    return result;
}
Exemple #12
0
/*=========================================================================*/
int SLPDDatabaseReg(SLPSrvReg* srvreg, unsigned int regtype)
/* Add a service registration to the database                              */
/*                                                                         */
/* srvreg   -   (IN) pointer to the SLPSrvReg to be added to the database  */
/*                                                                         */
/* regtype  -   (IN) registration types or'ed together:                    */
/*                   SLPDDATABASE_REG_FRESH                                */
/*                   SLPDDATABASE_REG_LOCAL                                */
/*                   SLPDDATABASE_REG_STATIC                               */
/*                                                                         */
/* Returns  -   Zero on success.  > 0 if something is wrong with srvreg    */
/*              < 0 if out of memory                                       */
/*                                                                         */
/* NOTE:        All registrations are treated as fresh regardless of the   */
/*              setting of the fresh parameter                             */
/*=========================================================================*/
{
    int                result = -1;
    SLPDDatabaseEntry* entry  = (SLPDDatabaseEntry*)G_DatabaseList.head;

    /* Check to see if there is already an identical entry */
    while(entry)
    {
        if(SLPCompareString(entry->urllen,
                            entry->url,
                            srvreg->urlentry.urllen,
                            srvreg->urlentry.url) == 0)
        {
            if(SLPIntersectStringList(entry->scopelistlen,
                                      entry->scopelist,
                                      srvreg->scopelistlen,
                                      srvreg->scopelist) > 0)
            {
                SLPListUnlink(&G_DatabaseList,(SLPListItem*)entry);
                break;
            }
        }

        entry = (SLPDDatabaseEntry*) entry->listitem.next;
    }

    /* if no identical entry are found, create a new one */
    if(entry == 0)
    {
        entry = SLPDDatabaseEntryAlloc();
        if(entry == 0)
        {
            /* Out of memory */
            goto FAILURE;
        }
    }

    /*----------------------------------------------------------------*/
    /* copy info from the message from the wire to the database entry */
    /*----------------------------------------------------------------*/

    /* scope */
    if(entry->scopelistlen >= srvreg->scopelistlen)
    {
        memcpy(entry->scopelist,srvreg->scopelist,srvreg->scopelistlen);
    }
    else
    {
        if(entry->scopelist) free(entry->scopelist);
        entry->scopelist = (char*)memdup(srvreg->scopelist,srvreg->scopelistlen);
        if(entry->scopelist == 0) goto FAILURE;
    }
    entry->scopelistlen = srvreg->scopelistlen;

    /* URL */
    if(entry->urllen >= srvreg->urlentry.urllen)
    {
        memcpy(entry->url,srvreg->urlentry.url,srvreg->urlentry.urllen);
    }
    else
    {
        if(entry->url) free(entry->url);
        entry->url = (char*)memdup(srvreg->urlentry.url,srvreg->urlentry.urllen);
        if(entry->url == 0) goto FAILURE;
    }
    entry->urllen = srvreg->urlentry.urllen;

    /* lifetime */
    entry->lifetime     = srvreg->urlentry.lifetime;

    /* is local */
    entry->regtype      = regtype;

    /* SrvType */
    if(entry->srvtypelen >= srvreg->srvtypelen)
    {
        memcpy(entry->srvtype,srvreg->srvtype,srvreg->srvtypelen);
    }
    else
    {
        if(entry->srvtype) free(entry->srvtype);
        entry->srvtype = (char*)memdup(srvreg->srvtype,srvreg->srvtypelen);
        if(entry->srvtype == 0) goto FAILURE;
    }
    entry->srvtypelen = srvreg->srvtypelen;

    /* Attributes */
    if(srvreg->attrlistlen)
    {
#ifdef USE_PREDICATES




        /* Tricky: perform an in place null termination of the attrlist */
        /*         Remember this squishes the authblock count           */
        ((char*)srvreg->attrlist)[srvreg->attrlistlen] = 0;
        if(SLPAttrFreshen(entry->attr, srvreg->attrlist) != SLP_OK)
        {
            result = 1;
            goto FAILURE;
        }

        /* Serialize all attributes into entry->attrlist */
        if(entry->attrlist)
        {
            free(entry->attrlist);
            entry->attrlist = 0;
            entry->attrlistlen = 0;
        }
        if(SLPAttrSerialize(entry->attr,
                            "",
                            &entry->attrlist,
                            entry->attrlistlen,
                            &entry->attrlistlen,
                            SLP_FALSE))
        {
            goto FAILURE;
        }
#else
        if(entry->attrlistlen >= srvreg->attrlistlen)
        {
            memcpy(entry->attrlist,srvreg->attrlist,srvreg->attrlistlen);
        }
        else
        {
            if(entry->attrlist) free(entry->attrlist);
            entry->attrlist = memdup(srvreg->attrlist,srvreg->attrlistlen);
            if(entry->attrlist == 0) goto FAILURE;
        }
        entry->attrlistlen = srvreg->attrlistlen;
#endif
    }

    /* link the new (or modified) entry into the list */
    SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry);

    /* traceReg if necessary */
    SLPDLogTraceReg("Registered", entry);

    return 0;

FAILURE:
    if(entry)
    {
        SLPDDatabaseEntryFree(entry);
    }

    return result;
}