/*=========================================================================*/ 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; }
/*=========================================================================*/ 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); } }
/*-------------------------------------------------------------------------*/ 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; }
/*=========================================================================*/ 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; }
/*-------------------------------------------------------------------------*/ 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); } } } }
/*-------------------------------------------------------------------------*/ 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; }
/** 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); }
/*=========================================================================*/ 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; }
/*-------------------------------------------------------------------------*/ 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); } } } }
/*=========================================================================*/ 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; }
/*=========================================================================*/ 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; }
/*=========================================================================*/ 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; }