/*=========================================================================*/ int KnownDADiscover(struct timeval* timeout) /* Returns: the number of DAs discovered */ /*=========================================================================*/ { int fd; int result = 0; /* TODO THIS FUNCTION MUST BE SYNCRONIZED !! */ /* two threads must not be in here at the same time */ /*----------------------------------------------------*/ /* Check values from the net.slp.DAAddresses property */ /*----------------------------------------------------*/ result = KnownDADiscoveryByProperties(timeout); if (result) { KnownDASaveHints(); return result; } /*------------------------------*/ /* Check data from DHCP Options */ /*------------------------------*/ /* TODO put code here when you can */ /*-----------------------------------*/ /* Load G_KnownDAListhead from hints */ /*-----------------------------------*/ fd = open(SLPGetProperty("net.slp.HintsFile"),O_RDONLY); if (fd >= 0) { SLPDAEntryListRead(fd, &G_KnownDAList); close(fd); if (G_KnownDAList.count) { return G_KnownDAList.count; } } /*-------------------*/ /* Multicast for DAs */ /*-------------------*/ if (SLPPropertyAsBoolean(SLPGetProperty("net.slp.activeDADetection")) && SLPPropertyAsInteger(SLPGetProperty("net.slp.DAActiveDiscoveryInterval"))) { result = KnownDADiscoveryByMulticast(); if (result) { KnownDASaveHints(); return result; } } return 0; }
/*-------------------------------------------------------------------------*/ int KnownDADiscoverFromProperties() /* Locates DAs from a list of DA hostnames */ /* */ /* Returns: number of *new* DAs found */ /*-------------------------------------------------------------------------*/ { char* temp; char* tempend; char* slider1; char* slider2; int sockfd; struct hostent* he; struct sockaddr_in peeraddr; struct timeval timeout; int result = 0; memset(&peeraddr,0,sizeof(peeraddr)); peeraddr.sin_family = AF_INET; peeraddr.sin_port = htons(SLP_RESERVED_PORT); slider1 = slider2 = temp = strdup(SLPGetProperty("net.slp.DAAddresses")); if(temp) { tempend = temp + strlen(temp); while(slider1 != tempend) { timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); timeout.tv_usec = (timeout.tv_sec % 1000) * 1000; timeout.tv_sec = timeout.tv_sec / 1000; while(*slider2 && *slider2 != ',') slider2++; *slider2 = 0; he = gethostbyname(slider1); if(he) { peeraddr.sin_addr.s_addr = *((unsigned int*)(he->h_addr_list[0])); sockfd = SLPNetworkConnectStream(&peeraddr,&timeout); if(sockfd >= 0) { result = KnownDADiscoveryRqstRply(sockfd,&peeraddr,0,""); close(sockfd); if(result) { break; } } } slider1 = slider2; slider2++; } free(temp); } return result; }
SLPBoolean AreWeADirectoryAgent( void ) { SLPBoolean isDA = SLP_FALSE; if ( SLPGetProperty("com.apple.slp.isDA") && !SDstrcasecmp(SLPGetProperty("com.apple.slp.isDA"),"true") ) isDA = SLP_TRUE; return isDA; }
void PrintVersion(SLPToolCommandLine * cmdline) { (void)cmdline; printf("slptool version = %s\n", SLP_VERSION); printf("libslp version = %s\n", SLPGetProperty("net.slp.OpenSLPVersion")); printf("libslp configuration file = %s\n", SLPGetProperty("net.slp.OpenSLPConfigFile")); }
/*=========================================================================*/ SLPError SLPFindScopes(SLPHandle hSLP, char** ppcScopeList) /* */ /* Sets ppcScopeList parameter to a pointer to a comma separated list */ /* including all available scope values. The list of scopes comes from */ /* a variety of sources: the configuration file's net.slp.useScopes */ /* property, unicast to DAs on the net.slp.DAAddresses property, DHCP, */ /* or through the DA discovery process. If there is any order to the */ /* scopes, preferred scopes are listed before less desirable scopes. */ /* There is always at least one name in the list, the default scope, */ /* "DEFAULT". */ /* */ /* hSLP The SLPHandle on which to search for scopes. */ /* */ /* ppcScopeList A pointer to char pointer into which the buffer pointer is */ /* placed upon return. The buffer is null terminated. The */ /* memory should be freed by calling SLPFree(). */ /* */ /* Returns: If no error occurs, returns SLP_OK, otherwise, the a */ /* ppropriate error code. */ /*=========================================================================*/ { /* TODO: Check DAs and DHCP */ *ppcScopeList = (char*)strdup(SLPGetProperty("net.slp.useScopes")); if(*ppcScopeList == 0) { return SLP_MEMORY_ALLOC_FAILED; } return SLP_OK; }
SLPError SLPOpen(const char *pcLang, SLPBoolean isAsync, SLPHandle *phSLP) { slp_handle_impl_t *hp; if (!pcLang || !phSLP) { return (SLP_PARAMETER_BAD); } /* allocate the handle */ if (!(hp = malloc(sizeof (*hp)))) { slp_err(LOG_CRIT, 0, "SLPOpen", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } /* initialize outcall synchronization */ hp->pending_outcall = SLP_FALSE; (void) mutex_init(&(hp->outcall_lock), NULL, NULL); (void) cond_init(&(hp->outcall_cv), NULL, NULL); hp->close_on_end = SLP_FALSE; hp->consumer_tid = 0; /* locale property overrides argument */ if (!(hp->locale = SLPGetProperty(SLP_CONFIG_LOCALE))) { hp->locale = pcLang; } /* Make sure the language string is under our ownership */ if (!(hp->locale = strdup(hp->locale))) { free(hp); slp_err(LOG_CRIT, 0, "SLPOpen", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } hp->cancel = 0; /* Asynchronous operation? */ if (isAsync) hp->async = SLP_TRUE; else hp->async = SLP_FALSE; /* TCP vars -- these are NULL until actually needed */ hp->tcp_lock = NULL; hp->tcp_wait = NULL; hp->tcp_ref_cnt = 0; /* Consumer / Producer pipe */ hp->q = NULL; /* Interface info, loaded on demand */ hp->ifinfo = NULL; /* force multicast, false by default */ hp->force_multicast = SLP_FALSE; /* internal call, false by default */ hp->internal_call = SLP_FALSE; *phSLP = hp; return (SLP_OK); }
void GetProperty(SLPToolCommandLine * cmdline) { const char * propertyValue; propertyValue = SLPGetProperty(cmdline->cmdparam1); printf("%s = %s\n", cmdline->cmdparam1, propertyValue == 0 ? "" : propertyValue); }
/*=========================================================================*/ int NetworkConnectToMulticast(struct sockaddr_in* peeraddr) /*=========================================================================*/ { int sock = -1; if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.isBroadcastOnly")) == 0) { sock = SLPNetworkConnectToMulticast(peeraddr, atoi(SLPGetProperty("net.slp.multicastTTL"))); } if (sock < 0) { sock = SLPNetworkConnectToBroadcast(peeraddr); } return sock; }
/*-------------------------------------------------------------------------*/ void KnownDASaveHints() /*-------------------------------------------------------------------------*/ { int fd; #ifdef WIN32 fd = creat(SLPGetProperty("net.slp.HintsFile"), _S_IREAD | _S_IWRITE); #else fd = creat(SLPGetProperty("net.slp.HintsFile"), S_IROTH | S_IWOTH | S_IRGRP| S_IWGRP | S_IRUSR | S_IWUSR); #endif if (fd >= 0) { SLPDAEntryListWrite(fd, &G_KnownDAList); close(fd); } }
/*=========================================================================*/ int NetworkConnectToDA(const char* scopelist, int scopelistlen, struct sockaddr_in* peeraddr) /* Connects to slpd and provides a peeraddr to send to */ /* */ /* scopelist (IN) Scope that must be supported by DA. Pass in NULL */ /* for any scope */ /* */ /* scopelistlen (IN) Length of the scope list in bytes. Ignored if */ /* scopelist is NULL */ /* */ /* peeraddr (OUT) pointer to receive the connected DA's address */ /* */ /* Returns Connected socket or -1 if no DA connection can be made */ /*=========================================================================*/ { time_t curtime; int dinterval; int sock; struct timeval timeout; timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); timeout.tv_usec = (timeout.tv_sec % 1000) * 1000; timeout.tv_sec = timeout.tv_sec / 1000; sock = KnownDAConnect(scopelist,scopelistlen,peeraddr,&timeout); if(sock < 0) { time(&curtime); dinterval = atoi(SLPGetProperty("net.slp.DAActiveDiscoveryInterval")); if(dinterval < MINIMUM_DISCOVERY_INTERVAL) { dinterval = MINIMUM_DISCOVERY_INTERVAL; } if(curtime - G_LastDADiscovery > dinterval) { KnownDADiscover(&timeout); sock = KnownDAConnect(scopelist,scopelistlen,peeraddr,&timeout); time(&G_LastDADiscovery); } } return sock; }
EXPORT SLPInternalError dat_get_da(const DATable *ignore, const char *pcScopeList, struct sockaddr_in *psin) { int i, found = 0; DATable* pdat = GetGlobalDATable(); // ignore what they pass in, only reference the globaly defined table SLPInternalError error = SLP_OK; if (!pdat || !pcScopeList || !psin) return SLP_PARAMETER_BAD; LockGlobalDATable(); psin->sin_addr.s_addr = 0L; /* Testing mode! Return no DA if this property is set */ if (SLPGetProperty("com.sun.slp.noDA") && !SDstrcasecmp(SLPGetProperty("com.sun.slp.noDA"),"true")) { error = SLP_OK; } else { for (i = 0; i < pdat->iSize; i++) { if (list_intersection(pcScopeList,pdat->pDAE[i].pcScopeList)) { *psin = pdat->pDAE[i].sin; found = 1; break; } } if ( pdat->iSize && !found ) { // we have DA's discovered but no nothing about the scope they are asking for... error = SLP_SCOPE_NOT_SUPPORTED; } } UnlockGlobalDATable(); return error; }
/*=========================================================================*/ void PrintVersion(SLPToolCommandLine* cmdline) /*=========================================================================*/ { #ifdef WIN32 printf("slptool version = %s\n",SLP_VERSION); #else printf("slptool version = %s\n",VERSION); #endif printf("OpenSLP version = %s\n", SLPGetProperty("net.slp.OpenSLPVersion")); }
/*-------------------------------------------------------------------------*/ int KnownDADiscoveryByProperties(struct timeval* timeout) /* Locates DAs from a list of DA hostnames */ /* */ /* Returns: number of DAs discovered */ /*-------------------------------------------------------------------------*/ { int result = 0; char* slider1; char* slider2; char* temp; char* tempend; int sock; struct hostent* he; struct sockaddr_in peeraddr; memset(&peeraddr,0,sizeof(peeraddr)); peeraddr.sin_family = AF_INET; peeraddr.sin_port = htons(SLP_RESERVED_PORT); slider1 = slider2 = temp = strdup(SLPGetProperty("net.slp.DAAddresses")); if (temp) { tempend = temp + strlen(temp); while (slider1 != tempend) { while (*slider2 && *slider2 != ',') slider2++; *slider2 = 0; he = gethostbyname(slider1); if (he) { peeraddr.sin_addr.s_addr = *((unsigned long*)(he->h_addr_list[0])); result += 1; sock = SLPNetworkConnectStream(&peeraddr,timeout); if (sock >= 0) { result += KnownDADiscoveryRqstRply(sock, &peeraddr); close(sock); } } slider1 = slider2; slider2++; } free(temp); } return result; }
static SLPInternalError fcopy(const char *pc1, const char *pc2) { struct stat st1; char buf[100]; FILE *fpSrc = NULL, *fpDest = NULL; int total; if (stat(pc1, &st1) < 0 || (fpSrc = fopen(pc1,"rb")) == NULL || (fpDest = fopen(pc2,"wb")) == NULL) { if (fpSrc) fclose(fpSrc); LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR, "fcopy: could not open both src and dest to copy", SLP_PARAMETER_BAD); } else { /* copy file 1 to file 2 */ total = st1.st_size; while (total > 0) { int xfer = (total > 100) ? 100 : total; int got; int wrote; if ((got = read(fileno(fpSrc),buf,xfer)) != xfer || (wrote = write(fileno(fpDest),buf,xfer)) != xfer) { fclose(fpSrc); fclose(fpDest); LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR, "fcopy: could not read temp or write reg file", SLP_INTERNAL_SYSTEM_ERROR); } total -= xfer; } // while (total > 0) if (SDchmod_writable(SLPGetProperty("com.sun.slp.regfile")) < 0) { SLP_LOG(SLP_LOG_ERR,"fcopy: could not change file permissions %s",strerror(errno)); fclose(fpSrc); fclose(fpDest); return SLP_PREFERENCES_ERROR; } if (fclose(fpSrc) || fclose(fpDest)) { LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR, "fcopy: could not close temp or reg file", SLP_INTERNAL_SYSTEM_ERROR); } } // else return SLP_OK; }
/*=========================================================================*/ int NetworkConnectToSlpMulticast(struct sockaddr_in* peeraddr) /* Creates a socket and connects it to the SLP multicast address */ /* */ /* Returns - Valid file descriptor on success, -1 on failure w/ errno set.*/ /*=========================================================================*/ { const char* bcastonly; int sockfd; int ttl; bcastonly = SLPGetProperty("net.slp.isBroadcastOnly"); if(*bcastonly == 'T' || *bcastonly == 't' || *bcastonly == 'Y' || *bcastonly == 'y') { return -1; } /* setup multicast socket */ sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd >= 0) { peeraddr->sin_family = AF_INET; peeraddr->sin_port = htons(SLP_RESERVED_PORT); peeraddr->sin_addr.s_addr = htonl(SLP_MCAST_ADDRESS); ttl = atoi(SLPGetProperty("net.slp.multicastTTL")); if(setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl))) { return -1; } } return sockfd; }
/*=========================================================================*/ int KnownDAConnect(int scopelistlen, const char* scopelist, struct sockaddr_in* peeraddr) /* Get a connected socket to a DA that supports the specified scope */ /* */ /* scopelistlen (IN) stringlen of the scopelist */ /* */ /* scopelist (IN) DA must support this scope */ /* */ /* peeraddr (OUT) the peer that was connected to */ /* */ /* */ /* returns: valid socket file descriptor or -1 if no DA is found */ /*=========================================================================*/ { struct timeval timeout; SLPDAEntry* daentry; int sock = -1; /* Set up connect timeout */ timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); timeout.tv_usec = (timeout.tv_sec % 1000) * 1000; timeout.tv_sec = timeout.tv_sec / 1000; while(1) { daentry = KnownDAFromCache(scopelistlen,scopelist); if(daentry == 0) { break; } memset(peeraddr,0,sizeof(peeraddr)); peeraddr->sin_family = AF_INET; peeraddr->sin_port = htons(SLP_RESERVED_PORT); peeraddr->sin_addr = daentry->daaddr; sock = SLPNetworkConnectStream(peeraddr,&timeout); if(sock >= 0) { break; } KnownDAListRemove(&G_KnownDACache,daentry); } return sock; }
static void exit_handler(int signo) { /* free resources ! */ #ifdef ENABLE_SLP_LOGGING SLP_LOG( SLP_LOG_STATE, "*** slpd exit has been called: (%d) ***", signo ); #endif close(global_resources.sdUDP); remove(SLPGetProperty("com.sun.slp.tempfile")); #ifdef SLPTCP close(global_resources.sdTCP); #endif /* SLPTCP */ #ifdef ENABLE_SLP_LOGGING if ( signo == SIGHUP ) { // we want to relaunch. Question is are we a child of watchdog? SLP_LOG( SLP_LOG_SIGNAL, "slpd's parent pid is %d", getppid() ); } #endif exit(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; }
/*=========================================================================*/ SLPError SLPDereg(SLPHandle hSLP, const char *srvUrl, SLPRegReport callback, void *cookie) /* */ /* See slplib.h for detailed documentation */ /*=========================================================================*/ { PSLPHandleInfo handle = 0; SLPError result = SLP_OK; SLPSrvURL* parsedurl = 0; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if( hSLP == 0 || *(unsigned long*)hSLP != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || /* url can't be empty string */ callback == 0) { return SLP_PARAMETER_BAD; } /*-----------------------------------------*/ /* cast the SLPHandle into a SLPHandleInfo */ /*-----------------------------------------*/ handle = (PSLPHandleInfo)hSLP; /*-----------------------------------------*/ /* Check to see if the handle is in use */ /*-----------------------------------------*/ if(handle->inUse == SLP_TRUE) { return SLP_HANDLE_IN_USE; } handle->inUse = SLP_TRUE; /*---------------------------------------------*/ /* Check to see if we can talk to a slpd */ /*---------------------------------------------*/ if(handle->slpdsock < 0) { /* slpd is not running locally and no DA's are configured */ handle->inUse = SLP_FALSE; return SLP_NETWORK_INIT_FAILED; } /*------------------*/ /* Parse the srvurl */ /*------------------*/ result = SLPParseSrvURL(srvUrl,&parsedurl); if(result) { if(result == SLP_PARSE_ERROR) { result = SLP_INVALID_REGISTRATION; } if(parsedurl) SLPFree(parsedurl); handle->inUse = SLP_FALSE; return result; } /*-------------------------------------------*/ /* Set the handle up to reference parameters */ /*-------------------------------------------*/ handle->params.dereg.scopelist = SLPGetProperty("net.slp.useScopes"); if(handle->params.dereg.scopelist) { handle->params.dereg.scopelistlen = strlen(handle->params.dereg.scopelist); } handle->params.dereg.urllen = strlen(srvUrl); handle->params.dereg.url = srvUrl; handle->params.dereg.callback = callback; handle->params.dereg.cookie = cookie; /*----------------------------------------------*/ /* Check to see if we should be async or sync */ /*----------------------------------------------*/ if(handle->isAsync) { /* COPY all the parameters */ handle->params.dereg.scopelist = strdup(handle->params.dereg.scopelist); handle->params.dereg.url = strdup(handle->params.dereg.url); /* make sure the strdups did not fail */ if(handle->params.dereg.scopelist && handle->params.dereg.url ) { result = ThreadCreate((ThreadStartProc)AsyncProcessSrvDeReg,handle); } else { result = SLP_MEMORY_ALLOC_FAILED; } if(result) { if(handle->params.dereg.scopelist) free((void*)handle->params.dereg.scopelist); if(handle->params.dereg.url) free((void*)handle->params.dereg.url); handle->inUse = SLP_FALSE; } } else { /* REFERENCE all the parameters */ result = ProcessSrvDeReg(handle); handle->inUse = SLP_FALSE; } if(parsedurl) SLPFree(parsedurl); return result; }
/*=========================================================================*/ int KnownDAConnect(PSLPHandleInfo handle, int scopelistlen, const char* scopelist, struct sockaddr_in* peeraddr) /* Get a connected socket to a DA that supports the specified scope */ /* */ /* scopelistlen (IN) stringlen of the scopelist */ /* */ /* scopelist (IN) DA must support this scope */ /* */ /* peeraddr (OUT) the peer that was connected to */ /* */ /* */ /* returns: valid socket file descriptor or -1 if no DA is found */ /*=========================================================================*/ { struct timeval timeout; int sock = -1; int spistrlen = 0; char* spistr = 0; #ifdef ENABLE_SLPv2_SECURITY if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"))) { SLPSpiGetDefaultSPI(handle->hspi, SLPSPI_KEY_TYPE_PUBLIC, &spistrlen, &spistr); } #endif /* Set up connect timeout */ timeout.tv_sec = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); timeout.tv_usec = (timeout.tv_sec % 1000) * 1000; timeout.tv_sec = timeout.tv_sec / 1000; while(1) { memset(peeraddr,0,sizeof(peeraddr)); if(KnownDAFromCache(scopelistlen, scopelist, spistrlen, spistr, &(peeraddr->sin_addr)) == 0) { break; } peeraddr->sin_family = PF_INET; peeraddr->sin_port = htons(SLP_RESERVED_PORT); sock = SLPNetworkConnectStream(peeraddr,&timeout); if(sock >= 0) { break; } KnownDABadDA(&(peeraddr->sin_addr)); } #ifdef ENABLE_SLPv2_SECURITY if(spistr) xfree(spistr); #endif return sock; }
/* * dat_get_scopes * * If there is a net.slp.useScopes property, these scopes are * returned. Otherwise, starting with the scope list of the first * element, each DA's list is merged in (looking individually at * each of the already-obtained scopes to see if there is a list * intersection with the scopes of each of the subsequent DAs.) * * If there are no configured scopes and no DAs, and SA discovery * functionality has been compiled in, then SA discovery will be * used to * * slph This is used for SA discovery if needed. * pcTypeHint This is used for SA discovery, to optimize it. * pdat The da table which is checked for a scope list. * ppcScopes The scope list to return (an OUT parameter.) * * Return: * * Error if any. * *ppcScopes is set to the scope list obtained. If no scopes have * been found, this parameter will be set to NULL. * * Side Effects: * * The string list returned in ppcScopes must be freed by the caller. * * Notes: * * SA discovery will be implemented later... * */ EXPORT SLPInternalError dat_get_scopes(SLPHandle slph, const char *pcTypeHint, const DATable *ignore, char **ppcScopes) { DATable* pdat = GetGlobalDATable(); char *pcList, *pcScan; int iListLen = LISTINCR; int i; LockGlobalDATable(); *ppcScopes = NULL; if (!pdat || !ppcScopes) return SLP_PARAMETER_BAD; if (SLPGetProperty("net.slp.useScopes") != NULL) { *ppcScopes = strdup(SLPGetProperty("net.slp.useScopes")); return SLP_OK; } #ifdef EXTRA_MSGS if (slph != NULL && pdat->iSize == 0) { active_sa_discovery(slph,pcTypeHint); if (pdat->pcSASList) { int iLen = strlen(pdat->pcSASList); *ppcScopes = safe_malloc(iLen+1,pdat->pcSASList,iLen); } return SLP_OK; } #endif /* EXTRA_MSGS */ /* send a merged list of scopes from the DATable */ if (pdat->iSize == 0) return SLP_OK; iListLen += strlen(pdat->pDAE[0].pcScopeList); pcList = safe_malloc(iListLen, (char*)pdat->pDAE[0].pcScopeList, iListLen-LISTINCR); if( !pcList ) return SLP_INTERNAL_SYSTEM_ERROR; if (pdat->iSize > 1) { for (i = 1; i < pdat->iSize; i++) { pcScan = list_pack(pdat->pDAE[i].pcScopeList); list_merge(pcScan,&pcList,&iListLen,CHECK); free(pcScan); } } *ppcScopes = pcList; UnlockGlobalDATable(); return SLP_OK; }
/*=========================================================================*/ SLPError SLPOpen(const char *pcLang, SLPBoolean isAsync, SLPHandle *phSLP) /* */ /* Returns a SLPHandle handle in the phSLP parameter for the language */ /* locale passed in as the pcLang parameter. The client indicates if */ /* operations on the handle are to be synchronous or asynchronous */ /* through the isAsync parameter. The handle encapsulates the language */ /* locale for SLP requests issued through the handle, and any other */ /* resources required by the implementation. However, SLP properties */ /* are not encapsulated by the handle; they are global. The return */ /* value of the function is an SLPError code indicating the status of */ /* the operation. Upon failure, the phSLP parameter is NULL. */ /* */ /* An SLPHandle can only be used for one SLP API operation at a time. */ /* If the original operation was started asynchronously, any attempt to */ /* start an additional operation on the handle while the original */ /* operation is pending results in the return of an SLP_HANDLE_IN_USE */ /* error from the API function. The SLPClose() API function terminates */ /* any outstanding calls on the handle. If an implementation is unable */ /* to support a asynchronous( resp. synchronous) operation, due to */ /* memory constraints or lack of threading support, the */ /* SLP_NOT_IMPLEMENTED flag may be returned when the isAsync flag is */ /* SLP_TRUE (resp. SLP_FALSE). */ /* */ /* pcLang A pointer to an array of characters containing the RFC 1766 */ /* Language Tag RFC 1766 for the natural language locale of */ /* requests and registrations issued on the handle. Pass in NULL */ /* or the empty string, "" to use the default locale */ /* */ /* isAsync An SLPBoolean indicating whether the SLPHandle should be opened*/ /* for asynchronous operation or not. */ /* */ /* phSLP A pointer to an SLPHandle, in which the open SLPHandle is */ /* returned. If an error occurs, the value upon return is NULL. */ /* */ /* Returns SLPError code */ /*=========================================================================*/ { SLPError result = SLP_OK; PSLPHandleInfo handle = 0; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if(phSLP == 0) { result = SLP_PARAMETER_BAD; goto FINISHED; } /* assign out param to zero in just for paranoia */ *phSLP = 0; /*-------------------------------------------------------*/ /* TODO: remove this line when you implement async calls */ /*-------------------------------------------------------*/ if(isAsync == SLP_TRUE) { result = SLP_NOT_IMPLEMENTED; goto FINISHED; } /*------------------------------------*/ /* allocate a SLPHandleInfo structure */ /*------------------------------------*/ handle = (PSLPHandleInfo)malloc(sizeof(SLPHandleInfo)); if(handle == 0) { result = SLP_PARAMETER_BAD; goto FINISHED; } memset(handle,0,sizeof(SLPHandleInfo)); /*-------------------------------*/ /* Set the language tag */ /*-------------------------------*/ if(pcLang && *pcLang) { handle->langtaglen = strlen(pcLang); handle->langtag = (char*)malloc(handle->langtaglen + 1); if(handle->langtag == 0) { free(handle); result = SLP_PARAMETER_BAD; goto FINISHED; } memcpy(handle->langtag,pcLang,handle->langtaglen + 1); } else { handle->langtaglen = strlen(SLPGetProperty("net.slp.locale")); handle->langtag = (char*)malloc(handle->langtaglen + 1); if(handle->langtag == 0) { free(handle); result = SLP_PARAMETER_BAD; goto FINISHED; } memcpy(handle->langtag,SLPGetProperty("net.slp.locale"),handle->langtaglen + 1); } /*---------------------------------------------------------*/ /* Seed the XID generator if this is the first open handle */ /*---------------------------------------------------------*/ if(G_OpenSLPHandleCount == 0) { #ifdef WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1,1); if (0 != WSAStartup(wVersionRequested, &wsaData)) { result = SLP_NETWORK_INIT_FAILED; goto FINISHED; } #endif SLPXidSeed(); } handle->inUse = SLP_FALSE; handle->isAsync = isAsync; handle->sig = SLP_HANDLE_SIG; G_OpenSLPHandleCount ++; *phSLP = (SLPHandle)handle; FINISHED: if(result) { *phSLP = 0; } return result; }
/* * dat_daadvert_in * * * Returns: * 1 if the Advert is new and stored services should be forwarded to it. * 0 otherwise. * if negative, it corresponds to a SLPInternalError. */ EXPORT int dat_daadvert_in(DATable *ignore, struct sockaddr_in sin, const char *pcScopeList, long lBootTime) { DATable* pdat = GetGlobalDATable(); int retval = 0; if (!pdat || !pcScopeList ) return SLP_PARAMETER_BAD; if (SLPGetProperty("com.sun.slp.noDA") && !SDstrcasecmp(SLPGetProperty("com.sun.slp.noDA"),"true")) return 0; if (lBootTime == 0) remove_dae(pdat,sin); else { int i,found = 0; LockGlobalDATable(); for (i = 0; i < pdat->iSize; i++) { if (pdat->pDAE[i].sin.sin_addr.s_addr == sin.sin_addr.s_addr) { found = 1; /* update the entry */ if (pdat->pDAE[i].lBootTime < lBootTime || strcmp(pcScopeList, pdat->pDAE[i].pcScopeList) != 0) { /* da rebooted or changed its scopelist */ pdat->pDAE[i].lBootTime = lBootTime; free(pdat->pDAE[i].pcScopeList); pdat->pDAE[i].pcScopeList = list_pack(pcScopeList); pdat->pDAE[i].iStrikes = 0; // reset this retval = 1; /* indicates a new entry */ if ( pdat->pDAE[i].iDAIsScopeSponser ) { // this DA told us what scope to use, we need to make sure that our default registration scope // hasn't changed. } #ifdef ENABLE_SLP_LOGGING SLP_LOG (SLP_LOG_MSG, "Updating DA [%s], in list with scopelist: %s", inet_ntoa(sin.sin_addr), pcScopeList ); #endif } break; } } if (found == 0) { /* add the daentry */ if ((pdat->iSize+1) == pdat->iMax) { /* resize the table if needed */ DAEntry *pdae = (DAEntry*) safe_malloc((pdat->iMax+DATINCR)*sizeof(DAEntry),(char*)pdat->pDAE, pdat->iMax*sizeof(DAEntry)); free(pdat->pDAE); pdat->pDAE = pdae; pdat->iMax += DATINCR; } pdat->pDAE[pdat->iSize].sin.sin_addr.s_addr = sin.sin_addr.s_addr; pdat->pDAE[pdat->iSize].sin.sin_family = AF_INET; pdat->pDAE[pdat->iSize].sin.sin_port = htons(SLP_PORT); pdat->pDAE[pdat->iSize].pcScopeList = list_pack(pcScopeList); pdat->pDAE[pdat->iSize].lBootTime = lBootTime; pdat->pDAE[pdat->iSize].iStrikes = 0; pdat->pDAE[pdat->iSize].iDAIsScopeSponser = false; pdat->iSize++; retval = 1; /* indicates a new entry */ #ifdef ENABLE_SLP_LOGGING SLP_LOG( SLP_LOG_MSG, "Adding DA [%s], to list with scopelist: %s", inet_ntoa(sin.sin_addr), pcScopeList ); #endif } UnlockGlobalDATable(); } return retval; }
/*=========================================================================*/ SLPError SLPAPI SLPFindSrvs(SLPHandle hSLP, const char *pcServiceType, const char *pcScopeList, const char *pcSearchFilter, SLPSrvURLCallback callback, void *pvCookie) /* */ /* Issue the query for services on the language specific SLPHandle and */ /* return the results through the callback. The parameters determine */ /* the results */ /* */ /* hSLP The language specific SLPHandle on which to search for */ /* services. */ /* */ /* pcServiceType The Service Type String, including authority string if */ /* any, for the request, such as can be discovered using */ /* SLPSrvTypes(). This could be, for example */ /* "service:printer:lpr" or "service:nfs". May not be */ /* the empty string or NULL. */ /* */ /* */ /* pcScopeList A pointer to a char containing comma separated list of */ /* scope names. Pass in the NULL or the empty string "" */ /* to find services in all the scopes the local host is */ /* configured query. */ /* */ /* pcSearchFilter A query formulated of attribute pattern matching */ /* expressions in the form of a LDAPv3 Search Filter. */ /* If this filter is NULL or empty, i.e. "", all */ /* services of the requested type in the specified scopes */ /* are returned. */ /* */ /* callback A callback function through which the results of the */ /* operation are reported. May not be NULL */ /* */ /* pvCookie Memory passed to the callback code from the client. */ /* May be NULL. */ /* */ /* Returns: If an error occurs in starting the operation, one of */ /* the SLPError codes is returned. */ /* */ /*=========================================================================*/ { PSLPHandleInfo handle; SLPError result; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if(hSLP == 0 || *(unsigned int*)hSLP != SLP_HANDLE_SIG || pcServiceType == 0 || *pcServiceType == 0 || /* srvtype can't be empty string */ callback == 0) { return SLP_PARAMETER_BAD; } /*-----------------------------------------*/ /* cast the SLPHandle into a SLPHandleInfo */ /*-----------------------------------------*/ handle = (PSLPHandleInfo)hSLP; /*-----------------------------------------*/ /* Check to see if the handle is in use */ /*-----------------------------------------*/ if(handle->inUse == SLP_TRUE) { return SLP_HANDLE_IN_USE; } handle->inUse = SLP_TRUE; /*-------------------------------------------*/ /* Set the handle up to reference parameters */ /*-------------------------------------------*/ handle->params.findsrvs.srvtypelen = strlen(pcServiceType); handle->params.findsrvs.srvtype = pcServiceType; if(pcScopeList && *pcScopeList) { handle->params.findsrvs.scopelistlen = strlen(pcScopeList); handle->params.findsrvs.scopelist = pcScopeList; } else { handle->params.findsrvs.scopelist = SLPGetProperty("net.slp.useScopes"); handle->params.findsrvs.scopelistlen = strlen(handle->params.findsrvs.scopelist); } if(pcSearchFilter) { handle->params.findsrvs.predicatelen = strlen(pcSearchFilter); handle->params.findsrvs.predicate = pcSearchFilter; } else { handle->params.findsrvs.predicatelen = 0; handle->params.findsrvs.predicate = (char*)&handle->params.findsrvs.predicatelen; } handle->params.findsrvs.callback = callback; handle->params.findsrvs.cookie = pvCookie; /*----------------------------------------------*/ /* Check to see if we should be async or sync */ /*----------------------------------------------*/ #ifdef ENABLE_ASYNC_API if(handle->isAsync) { /* COPY all the referenced parameters */ handle->params.findsrvs.srvtype = xstrdup(handle->params.findsrvs.srvtype); handle->params.findsrvs.scopelist = xstrdup(handle->params.findsrvs.scopelist); handle->params.findsrvs.predicate = xstrdup(handle->params.findsrvs.predicate); /* make sure strdups did not fail */ if(handle->params.findsrvs.srvtype && handle->params.findsrvs.scopelist && handle->params.findsrvs.predicate) { result = ThreadCreate((ThreadStartProc)AsyncProcessSrvRqst,handle); } else { result = SLP_MEMORY_ALLOC_FAILED; } if(result) { if(handle->params.findsrvs.srvtype) xfree((void*)handle->params.findsrvs.srvtype); if(handle->params.findsrvs.scopelist) xfree((void*)handle->params.findsrvs.scopelist); if(handle->params.findsrvs.predicate) xfree((void*)handle->params.findsrvs.predicate); handle->inUse = SLP_FALSE; } } else #endif /* ifdef ENABLE_ASYNC_API */ { /* Leave all parameters REFERENCED */ result = ProcessSrvRqst(handle); handle->inUse = SLP_FALSE; } return result; }
/*-------------------------------------------------------------------------*/ SLPBoolean ColateSLPSrvURLCallback(SLPHandle hSLP, const char* pcSrvURL, unsigned short sLifetime, SLPError errCode, void *pvCookie) /*-------------------------------------------------------------------------*/ { SLPSrvUrlColatedItem* collateditem; PSLPHandleInfo handle; handle = (PSLPHandleInfo) hSLP; handle->callbackcount ++; #ifdef ENABLE_ASYNC_API /* Do not colate for async calls */ if(handle->isAsync) { return handle->params.findsrvs.callback(hSLP, pcSrvURL, sLifetime, errCode, pvCookie); } #endif if(errCode == SLP_LAST_CALL || handle->callbackcount > SLPPropertyAsInteger(SLPGetProperty("net.slp.maxResults"))) { /* We are done so call the caller's callback for each */ /* service URL colated item and clean up the colation list */ handle->params.findsrvs.callback((SLPHandle)handle, NULL, 0, SLP_LAST_CALL, handle->params.findsrvs.cookie); goto CLEANUP; } else if(errCode != SLP_OK) { return SLP_TRUE; } /* Add the service URL to the colation list */ collateditem = (SLPSrvUrlColatedItem*) handle->collatedsrvurls.head; while(collateditem) { if(strcmp(collateditem->srvurl,pcSrvURL) == 0) { break; } collateditem = (SLPSrvUrlColatedItem*)collateditem->listitem.next; } /* create a new item if none was found */ if(collateditem == NULL) { collateditem = (SLPSrvUrlColatedItem*) xmalloc(sizeof(SLPSrvUrlColatedItem) + \ strlen(pcSrvURL) + 1); if(collateditem) { memset(collateditem,0,sizeof(SLPSrvUrlColatedItem)); collateditem->srvurl = (char*)(collateditem + 1); strcpy(collateditem->srvurl,pcSrvURL); collateditem->lifetime = sLifetime; /* Add the new item to the collated list */ SLPListLinkTail(&(handle->collatedsrvurls), (SLPListItem*)collateditem); /* Call the caller's callback */ if(handle->params.findsrvs.callback((SLPHandle)handle, pcSrvURL, sLifetime, SLP_OK, handle->params.findsrvs.cookie) == SLP_FALSE) { goto CLEANUP; } } } return SLP_TRUE; CLEANUP: /* free the collation list */ while(handle->collatedsrvurls.count) { collateditem = (SLPSrvUrlColatedItem*)SLPListUnlink(&(handle->collatedsrvurls), handle->collatedsrvurls.head); xfree(collateditem); } handle->callbackcount = 0; return SLP_FALSE; }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvRqst(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { struct sockaddr_in peeraddr; int sock = -1; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; #ifdef ENABLE_SLPv2_SECURITY int spistrlen = 0; char* spistr = 0; #endif /*------------------------------------------*/ /* Is this a special attempt to locate DAs? */ /*------------------------------------------*/ if(strncasecmp(handle->params.findsrvs.srvtype, SLP_DA_SERVICE_TYPE, handle->params.findsrvs.srvtypelen) == 0) { KnownDAProcessSrvRqst(handle); goto FINISHED; } #ifdef ENABLE_SLPv2_SECURITY if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"))) { SLPSpiGetDefaultSPI(handle->hspi, SLPSPI_KEY_TYPE_PUBLIC, &spistrlen, &spistr); } #endif /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVRQST */ /*-------------------------------------------------------------------*/ bufsize = handle->params.findsrvs.srvtypelen + 2; /* 2 bytes for len field */ bufsize += handle->params.findsrvs.scopelistlen + 2; /* 2 bytes for len field */ bufsize += handle->params.findsrvs.predicatelen + 2; /* 2 bytes for len field */ bufsize += 2; /* 2 bytes for spistr len*/ #ifdef ENABLE_SLPv2_SECURITY bufsize += spistrlen; #endif buf = curpos = (char*)xmalloc(bufsize); if(buf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVRQST */ /*------------------------------------------------------------*/ /* service type */ ToUINT16(curpos,handle->params.findsrvs.srvtypelen); curpos = curpos + 2; memcpy(curpos, handle->params.findsrvs.srvtype, handle->params.findsrvs.srvtypelen); curpos = curpos + handle->params.findsrvs.srvtypelen; /* scope list */ ToUINT16(curpos,handle->params.findsrvs.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen); curpos = curpos + handle->params.findsrvs.scopelistlen; /* predicate */ ToUINT16(curpos,handle->params.findsrvs.predicatelen); curpos = curpos + 2; memcpy(curpos, handle->params.findsrvs.predicate, handle->params.findsrvs.predicatelen); curpos = curpos + handle->params.findsrvs.predicatelen; #ifdef ENABLE_SLPv2_SECURITY ToUINT16(curpos,spistrlen); curpos = curpos + 2; memcpy(curpos,spistr,spistrlen); curpos = curpos + spistrlen; #else ToUINT16(curpos,0); #endif /*--------------------------*/ /* Call the RqstRply engine */ /*--------------------------*/ do { #ifndef UNICAST_NOT_SUPPORTED if ( handle->dounicast == 1 ) { void *cookie = (PSLPHandleInfo) handle; result = NetworkUcastRqstRply(handle, buf, SLP_FUNCT_SRVRQST, bufsize, ProcessSrvRplyCallback, cookie); break; } else #endif if(strncasecmp(handle->params.findsrvs.srvtype, SLP_SA_SERVICE_TYPE, handle->params.findsrvs.srvtypelen)) { sock = NetworkConnectToDA(handle, handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen, &peeraddr); } if(sock == -1) { /* use multicast as a last resort */ #ifndef MI_NOT_SUPPORTED result = NetworkMcastRqstRply(handle, buf, SLP_FUNCT_SRVRQST, bufsize, ProcessSrvRplyCallback, NULL); #else result = NetworkMcastRqstRply(handle->langtag, buf, SLP_FUNCT_SRVRQST, bufsize, ProcessSrvRplyCallback, handle); #endif /* MI_NOT_SUPPORTED */ break; } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, 0, buf, SLP_FUNCT_SRVRQST, bufsize, ProcessSrvRplyCallback, handle); if(result) { NetworkDisconnectDA(handle); } }while(result == SLP_NETWORK_ERROR); FINISHED: if(buf) xfree(buf); #ifdef ENABLE_SLPv2_SECURITY if(spistr) xfree(spistr); #endif return result; }
/*-------------------------------------------------------------------------*/ SLPBoolean ProcessSrvRplyCallback(SLPError errorcode, struct sockaddr_in* peerinfo, SLPBuffer replybuf, void* cookie) /*-------------------------------------------------------------------------*/ { int i; SLPUrlEntry* urlentry; SLPMessage replymsg; PSLPHandleInfo handle = (PSLPHandleInfo) cookie; SLPBoolean result = SLP_TRUE; #ifdef ENABLE_SLPv2_SECURITY int securityenabled; securityenabled = SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled")); #endif /*-------------------------------------------*/ /* Check the errorcode and bail if it is set */ /*-------------------------------------------*/ if(errorcode != SLP_OK) { return ColateSLPSrvURLCallback((SLPHandle)handle, 0, 0, errorcode, handle->params.findsrvs.cookie); } /*--------------------*/ /* Parse the replybuf */ /*--------------------*/ replymsg = SLPMessageAlloc(); if(replymsg) { if(SLPMessageParseBuffer(peerinfo,replybuf,replymsg) == 0) { if(replymsg->header.functionid == SLP_FUNCT_SRVRPLY && replymsg->body.srvrply.errorcode == 0) { urlentry = replymsg->body.srvrply.urlarray; for(i=0;i<replymsg->body.srvrply.urlcount;i++) { #ifdef ENABLE_SLPv2_SECURITY /*-------------------------------*/ /* Validate the authblocks */ /*-------------------------------*/ if(securityenabled && SLPAuthVerifyUrl(handle->hspi, 1, &(urlentry[i]))) { /* authentication failed skip this URLEntry */ continue; } #endif /*--------------------------------*/ /* Send the URL to the API caller */ /*--------------------------------*/ /* TRICKY: null terminate the url by setting the authcount to 0 */ ((char*)(urlentry[i].url))[urlentry[i].urllen] = 0; result = ColateSLPSrvURLCallback((SLPHandle)handle, urlentry[i].url, (unsigned short)urlentry[i].lifetime, SLP_OK, handle->params.findsrvs.cookie); if(result == SLP_FALSE) { break; } } } else if(replymsg->header.functionid == SLP_FUNCT_DAADVERT && replymsg->body.daadvert.errorcode == 0) { #ifdef ENABLE_SLPv2_SECURITY if(securityenabled && SLPAuthVerifyDAAdvert(handle->hspi, 1, &(replymsg->body.daadvert))) { /* Verification failed. Ignore message */ SLPMessageFree(replymsg); return SLP_TRUE; } #endif ((char*)(replymsg->body.daadvert.url))[replymsg->body.daadvert.urllen] = 0; result = ColateSLPSrvURLCallback((SLPHandle)handle, replymsg->body.daadvert.url, SLP_LIFETIME_MAXIMUM, SLP_OK, handle->params.findsrvs.cookie); } else if(replymsg->header.functionid == SLP_FUNCT_SAADVERT) { #ifdef ENABLE_SLPv2_SECURITY if(securityenabled && SLPAuthVerifySAAdvert(handle->hspi, 1, &(replymsg->body.saadvert))) { /* Verification failed. Ignore message */ SLPMessageFree(replymsg); return SLP_TRUE; } #endif ((char*)(replymsg->body.saadvert.url))[replymsg->body.saadvert.urllen] = 0; result = ColateSLPSrvURLCallback((SLPHandle)handle, replymsg->body.saadvert.url, SLP_LIFETIME_MAXIMUM, SLP_OK, handle->params.findsrvs.cookie); } } SLPMessageFree(replymsg); } return result; }
/*=========================================================================*/ void KnownDADiscover(struct timeval* timeout) /*=========================================================================*/ { int fd; struct stat hintstat; const char* hintfile = SLPGetProperty("net.slp.HintsFile"); /* TODO THIS FUNCTION MUST BE SYNCRONIZED !! */ /*-------------------------------------------*/ /* Check hints file to and load it if it */ /*-------------------------------------------*/ if(stat(hintfile,&hintstat) == 0) { if(hintstat.st_mtime != G_HintStat.st_mtime) { fd = open(hintfile,O_RDONLY); if(fd >= 0) { SLPDAEntryListRead(fd, &G_KnownDAListHead); close(fd); } } } /* if (hints file changed) */ /* { */ /* if(load hints file) */ /* { */ /* return; */ /* } */ /* } */ /* The logic of the following if(G_KnownDAListHead) statements is an */ /* attempt to reduce wasted time and network bandwidth due to unneeded */ /* communication with DAs and multicast */ if(G_KnownDAListHead == 0) { /*----------------------------------------------------*/ /* Check values from the net.slp.DAAddresses property */ /*----------------------------------------------------*/ KnownDADiscoveryByProperties(timeout); /*------------------------------*/ /* Check data from DHCP Options */ /*------------------------------*/ if(G_KnownDAListHead) { return; } } /*-------------*/ /* IPC to slpd */ /*-------------*/ /*-------------------*/ /* Multicast for DAs */ /*-------------------*/ if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.activeDADetection")) && SLPPropertyAsInteger(SLPGetProperty("net.slp.DAActiveDiscoveryInterval"))) { KnownDADiscoveryByMulticast(); } /*---------------------*/ /* Save the hints file */ /*---------------------*/ fd = open(hintfile, O_RDONLY | O_CREAT, S_IROTH | S_IWOTH | S_IRGRP| S_IWGRP | S_IRUSR, S_IWUSR); if(fd >= 0) { SLPDAEntryListWrite(fd, &G_KnownDAListHead); close(fd); stat(hintfile,&G_HintStat); } }
/*=========================================================================*/ SLPError SLPReg(SLPHandle hSLP, const char *srvUrl, const unsigned short lifetime, const char *srvType, const char *attrList, SLPBoolean fresh, SLPRegReport callback, void *cookie) /* */ /* See slplib.h for detailed documentation */ /*=========================================================================*/ { PSLPHandleInfo handle = 0; SLPError result = SLP_OK; SLPSrvURL* parsedurl = 0; /*------------------------------*/ /* check for invalid parameters */ /*------------------------------*/ if(hSLP == 0 || *(unsigned int*)hSLP != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || /* srvUrl can't be empty string */ lifetime == 0 || /* lifetime can not be zero */ attrList == 0 || callback == 0) { return SLP_PARAMETER_BAD; } /*-----------------------------------------*/ /* We don't handle fresh registrations */ /*-----------------------------------------*/ if(fresh == SLP_FALSE) { return SLP_NOT_IMPLEMENTED; } /*-----------------------------------------*/ /* cast the SLPHandle into a SLPHandleInfo */ /*-----------------------------------------*/ handle = (PSLPHandleInfo)hSLP; /*-----------------------------------------*/ /* Check to see if the handle is in use */ /*-----------------------------------------*/ if(handle->inUse == SLP_TRUE) { return SLP_HANDLE_IN_USE; } handle->inUse = SLP_TRUE; /*------------------*/ /* Parse the srvurl */ /*------------------*/ result = SLPParseSrvURL(srvUrl,&parsedurl); if(result) { if(result == SLP_PARSE_ERROR) { result = SLP_INVALID_REGISTRATION; } if(parsedurl) SLPFree(parsedurl); handle->inUse = SLP_FALSE; return result; } /*-------------------------------------------*/ /* Set the handle up to reference parameters */ /*-------------------------------------------*/ handle->params.reg.fresh = fresh; handle->params.reg.lifetime = lifetime; handle->params.reg.urllen = strlen(srvUrl); handle->params.reg.url = srvUrl; handle->params.reg.srvtype = parsedurl->s_pcSrvType; handle->params.reg.srvtypelen = strlen(handle->params.reg.srvtype); handle->params.reg.scopelist = SLPGetProperty("net.slp.useScopes"); if(handle->params.reg.scopelist) { handle->params.reg.scopelistlen = strlen(handle->params.reg.scopelist); } handle->params.reg.attrlistlen = strlen(attrList); handle->params.reg.attrlist = attrList; handle->params.reg.callback = callback; handle->params.reg.cookie = cookie; #ifdef ENABLE_ASYNC_API /*----------------------------------------------*/ /* Check to see if we should be async or sync */ /*----------------------------------------------*/ if(handle->isAsync) { /* Copy all of the referenced parameters before making thread */ handle->params.reg.url = xstrdup(handle->params.reg.url); handle->params.reg.srvtype = xstrdup(handle->params.reg.url); handle->params.reg.scopelist = xstrdup(handle->params.reg.scopelist); handle->params.reg.attrlist = xstrdup(handle->params.reg.attrlist); /* make sure that the strdups did not fail */ if(handle->params.reg.url && handle->params.reg.srvtype && handle->params.reg.scopelist && handle->params.reg.attrlist) { result = ThreadCreate((ThreadStartProc)AsyncProcessSrvReg,handle); } else { result = SLP_MEMORY_ALLOC_FAILED; } if(result) { if(handle->params.reg.url) xfree((void*)handle->params.reg.url); if(handle->params.reg.srvtype) xfree((void*)handle->params.reg.srvtype); if(handle->params.reg.scopelist) xfree((void*)handle->params.reg.scopelist); if(handle->params.reg.attrlist) xfree((void*)handle->params.reg.attrlist); handle->inUse = SLP_FALSE; } } else #endif //ffdef ENABLE_ASYNC_API { result = ProcessSrvReg(handle); handle->inUse = SLP_FALSE; } if(parsedurl) SLPFree(parsedurl); return result; }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvReg(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { int sock; struct sockaddr_in peeraddr; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; #ifdef ENABLE_SECURITY int urlauthlen = 0; unsigned char* urlauth = 0; int attrauthlen = 0; unsigned char* attrauth = 0; if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"))) { result = SLPAuthSignUrl(handle->hspi, 0, 0, handle->params.reg.urllen, handle->params.reg.url, &urlauthlen, &urlauth); if(result == 0) { result = SLPAuthSignString(handle->hspi, 0, 0, handle->params.reg.attrlistlen, handle->params.reg.attrlist, &attrauthlen, &attrauth); } bufsize += urlauthlen; bufsize += attrauthlen; } #endif /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVREG */ /*-------------------------------------------------------------------*/ bufsize += handle->params.reg.urllen + 6; /* 1 byte for reserved */ /* 2 bytes for lifetime */ /* 2 bytes for urllen */ /* 1 byte for authcount */ bufsize += handle->params.reg.srvtypelen + 2; /* 2 bytes for len field */ bufsize += handle->params.reg.scopelistlen + 2; /* 2 bytes for len field */ bufsize += handle->params.reg.attrlistlen + 2; /* 2 bytes for len field */ bufsize += 1; /* 1 byte for authcount */ buf = curpos = (char*)xmalloc(bufsize); if(buf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVREG */ /*------------------------------------------------------------*/ /* url-entry reserved */ *curpos= 0; curpos = curpos + 1; /* url-entry lifetime */ ToUINT16(curpos,handle->params.reg.lifetime); curpos = curpos + 2; /* url-entry urllen */ ToUINT16(curpos,handle->params.reg.urllen); curpos = curpos + 2; /* url-entry url */ memcpy(curpos, handle->params.reg.url, handle->params.reg.urllen); curpos = curpos + handle->params.reg.urllen; /* url-entry authblock */ #ifdef ENABLE_SECURITY if(urlauth) { /* authcount */ *curpos = 1; curpos = curpos + 1; /* authblock */ memcpy(curpos,urlauth,urlauthlen); curpos = curpos + urlauthlen; } else #endif { /* authcount */ *curpos = 0; curpos = curpos + 1; } /* service type */ ToUINT16(curpos,handle->params.reg.srvtypelen); curpos = curpos + 2; memcpy(curpos, handle->params.reg.srvtype, handle->params.reg.srvtypelen); curpos = curpos + handle->params.reg.srvtypelen; /* scope list */ ToUINT16(curpos,handle->params.reg.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.reg.scopelist, handle->params.reg.scopelistlen); curpos = curpos + handle->params.reg.scopelistlen; /* attr list */ ToUINT16(curpos,handle->params.reg.attrlistlen); curpos = curpos + 2; memcpy(curpos, handle->params.reg.attrlist, handle->params.reg.attrlistlen); curpos = curpos + handle->params.reg.attrlistlen; /* attribute auth block */ #ifdef ENABLE_SECURITY if(attrauth) { /* authcount */ *curpos = 1; curpos = curpos + 1; /* authblock */ memcpy(curpos,attrauth,attrauthlen); curpos = curpos + attrauthlen; } else #endif { /* authcount */ *curpos = 0; curpos = curpos + 1; } /*--------------------------*/ /* Call the RqstRply engine */ /*--------------------------*/ do { sock = NetworkConnectToSA(handle, handle->params.reg.scopelist, handle->params.reg.scopelistlen, &peeraddr); if(sock == -1) { result = SLP_NETWORK_INIT_FAILED; break; } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, buf, SLP_FUNCT_SRVREG, bufsize, CallbackSrvReg, handle); if(result) { NetworkDisconnectSA(handle); } }while(result == SLP_NETWORK_ERROR); FINISHED: if(buf) xfree(buf); #ifdef ENABLE_SECURITY if(urlauth) xfree(urlauth); if(attrauth) xfree(attrauth); #endif return result; }