/*-------------------------------------------------------------------------*/ int KnownDADiscoveryRqstRply(int sock, struct sockaddr_in* peeraddr, int scopelistlen, const char* scopelist) /* Returns: number of *new* DAEntries found */ /*-------------------------------------------------------------------------*/ { char* buf; char* curpos; int bufsize; int result = 0; /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVRQST */ /*-------------------------------------------------------------------*/ bufsize = 31; /* 2 bytes for the srvtype length */ /* 23 bytes for "service:directory-agent" srvtype */ /* 2 bytes for scopelistlen */ /* 2 bytes for predicatelen */ /* 2 bytes for sprstrlen */ bufsize += scopelistlen; /* TODO: make sure that we don't exceed the MTU */ buf = curpos = (char*)xmalloc(bufsize); if(buf == 0) { return 0; } memset(buf,0,bufsize); /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVRQST */ /*------------------------------------------------------------*/ /* service type */ ToUINT16(curpos,23); curpos = curpos + 2; /* 23 is the length of SLP_DA_SERVICE_TYPE */ memcpy(curpos,SLP_DA_SERVICE_TYPE,23); curpos += 23; /* scope list */ ToUINT16(curpos,scopelistlen); curpos = curpos + 2; memcpy(curpos,scopelist,scopelistlen); /* predicate zero length */ /* spi list zero length */ NetworkRqstRply(sock, peeraddr, "en", buf, SLP_FUNCT_DASRVRQST, bufsize, KnownDADiscoveryCallback, &result); xfree(buf); return result; }
/*-------------------------------------------------------------------------*/ int KnownDADiscoveryRqstRply(int sock, struct sockaddr_in* peeraddr) /*-------------------------------------------------------------------------*/ { int result = 0; char* buf; char* curpos; int bufsize; /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVRQST */ /*-------------------------------------------------------------------*/ bufsize = 31; /* 2 bytes for the srvtype length */ /* 23 bytes for "service:directory-agent" srvtype */ /* 2 bytes for scopelistlen */ /* 2 bytes for predicatelen */ /* 2 bytes for sprstrlen */ /* TODO: make sure that we don't exceed the MTU */ buf = curpos = (char*)malloc(bufsize); if(buf == 0) { return 0; } memset(buf,0,bufsize); /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVRQST */ /*------------------------------------------------------------*/ /* service type */ ToUINT16(curpos,23); curpos = curpos + 2; memcpy(curpos,"service:directory-agent",23); /* scope list zero length */ /* predicate zero length */ /* spi list zero length */ NetworkRqstRply(sock, peeraddr, "en", buf, SLP_FUNCT_DASRVRQST, bufsize, KnownDADiscoveryCallback, &result); free(buf); return result; }
/*-------------------------------------------------------------------------*/ void ProcessSrvReg(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int errorcode; if(message->header.flags & SLP_FLAG_MCAST) { /* don't do anything multicast SrvReg (set result empty) */ result->end = result->start; return; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPIntersectStringList(message->body.srvreg.scopelistlen, message->body.srvreg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*-------------------------------*/ /* TODO: Validate the authblocks */ /*-------------------------------*/ /*---------------------------------*/ /* put the service in the database */ /*---------------------------------*/ #ifdef WIN32 if(SLPDDatabaseReg(&(message->body.srvreg), message->header.flags | SLP_FLAG_FRESH, GetCurrentProcessId(), 0) == 0) /* TODO: Find an equivalent to user id on Win32*/ #else if(SLPDDatabaseReg(&(message->body.srvreg), message->header.flags | SLP_FLAG_FRESH, getpid(), getuid()) == 0) #endif { errorcode = 0; } else { errorcode = SLP_ERROR_INTERNAL_ERROR; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result,message->header.langtaglen + 16); /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT24(result->start + 2,message->header.langtaglen + 16); /*flags*/ ToUINT16(result->start + 5,0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 14 + message->header.langtaglen, errorcode); }
/*-------------------------------------------------------------------------*/ void ProcessSrvRqst(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int i; int size = 0; int count = 0; int found = 0; SLPDDatabaseSrvUrl* srvarray = 0; int errorcode = 0; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPStringListIntersect(message->body.srvrqst.prlistlen, message->body.srvrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; return; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPStringListIntersect(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) == 0) { result->end = result->start; return; } /*-------------------------------*/ /* Find services in the database */ /*-------------------------------*/ while(found == count) { count += SLPDPROCESS_RESULT_COUNT; if(srvarray) free(srvarray); srvarray = (SLPDDatabaseSrvUrl*)malloc(sizeof(SLPDDatabaseSrvUrl) * count); if(srvarray == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } found = SLPDDatabaseFindSrv(&(message->body.srvrqst), srvarray, count); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(found <= 0 && (message->header.flags & SLP_FLAG_MCAST)) { if(srvarray) free(srvarray); result->end = result->start; return; } /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for url count */ for(i=0;i<found;i++) { size += srvarray[i].urllen + 6; /* 1 byte for reserved */ /* 2 bytes for lifetime */ /* 2 bytes for urllen */ /* 1 byte for authcount */ /* TODO: Fix this for authentication */ } result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVRPLY; /*length*/ ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------------*/ /* Add rest of the SrvRply */ /*-------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; /* urlentry count */ ToUINT16(result->curpos, found); result->curpos = result->curpos + 2; for(i=0;i<found;i++) { /* url-entry reserved */ *result->curpos = 0; result->curpos = result->curpos + 1; /* url-entry lifetime */ ToUINT16(result->curpos,srvarray[i].lifetime); result->curpos = result->curpos + 2; /* url-entry urllen */ ToUINT16(result->curpos,srvarray[i].urllen); result->curpos = result->curpos + 2; /* url-entry url */ memcpy(result->curpos,srvarray[i].url,srvarray[i].urllen); result->curpos = result->curpos + srvarray[i].urllen; /* url-entry authcount */ *result->curpos = 0; result->curpos = result->curpos + 1; /* TODO: put in authentication stuff too */ } if(srvarray) free(srvarray); }
/*-------------------------------------------------------------------------*/ void ProcessSrvDeReg(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int errorcode; if(message->header.flags & SLP_FLAG_MCAST) { /* don't do anything multicast SrvDeReg (set result empty) */ result->end = result->start; return; } /*------------------------------------------*/ /* TODO: make sure that we handle the scope */ /*------------------------------------------*/ if(SLPStringListIntersect(message->body.srvdereg.scopelistlen, message->body.srvdereg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*-------------------------------*/ /* TODO: Validate the authblocks */ /*-------------------------------*/ /*--------------------------------------*/ /* remove the service from the database */ /*--------------------------------------*/ if(SLPDDatabaseDeReg(&(message->body.srvdereg)) == 0) { errorcode = 0; } else { errorcode = SLP_ERROR_INTERNAL_ERROR; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result,message->header.langtaglen + 16); /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT24(result->start + 2,message->header.langtaglen + 16); /*flags*/ ToUINT16(result->start + 5,0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 14 + message->header.langtaglen, errorcode); }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvRqst(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { struct sockaddr_in peeraddr; int sock = 0; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; /*-------------------------------------------------------------------*/ /* 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*/ /* TODO: make sure that we don't exceed the MTU */ buf = curpos = (char*)malloc(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; /* TODO: add spi list stuff here later*/ ToUINT16(curpos,0); /*---------------------------------------*/ /* Connect to DA, multicast or broadcast */ /*---------------------------------------*/ sock = NetworkConnectToDA(handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen, &peeraddr); if(sock < 0) { sock = NetworkConnectToMulticast(&peeraddr); if(sock < 0) { result = SLP_NETWORK_INIT_FAILED; goto FINISHED; } } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, buf, SLP_FUNCT_SRVRQST, bufsize, CallbackSrvRqst, handle); FINISHED: if(buf) free(buf); return result; }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvDeReg(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { int sock; struct sockaddr_in peeraddr; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVREG */ /*-------------------------------------------------------------------*/ bufsize += handle->params.dereg.scopelistlen + 2; /* 2 bytes for len field*/ bufsize += handle->params.dereg.urllen + 8; /* 1 byte for reserved */ /* 2 bytes for lifetime */ /* 2 bytes for urllen */ /* 1 byte for authcount */ bufsize += 2; /* 2 bytes for taglistlen*/ /* TODO: Fix this for authentication */ buf = curpos = (char*)malloc(bufsize); if(buf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVDEREG*/ /*------------------------------------------------------------*/ /* scope list */ ToUINT16(curpos,handle->params.dereg.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.dereg.scopelist, handle->params.dereg.scopelistlen); curpos = curpos + handle->params.dereg.scopelistlen; /* url-entry reserved */ *curpos = 0; curpos = curpos + 1; /* url-entry lifetime */ ToUINT16(curpos, 0); curpos = curpos + 2; /* url-entry urllen */ ToUINT16(curpos,handle->params.dereg.urllen); curpos = curpos + 2; /* url-entry url */ memcpy(curpos, handle->params.dereg.url, handle->params.dereg.urllen); curpos = curpos + handle->params.dereg.urllen; /* url-entry authcount */ *curpos = 0; curpos = curpos + 1; /* TODO: put in urlentry authentication stuff */ /* tag list */ /* TODO: put in taglist stuff */ ToUINT16(curpos,0); /*--------------------------*/ /* Call the RqstRply engine */ /*--------------------------*/ do { sock = NetworkConnectToSA(handle, handle->params.dereg.scopelist, handle->params.dereg.scopelistlen, &peeraddr); if(sock == -1) { result = SLP_NETWORK_INIT_FAILED; break; } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, buf, SLP_FUNCT_SRVDEREG, bufsize, CallbackSrvDeReg, handle); if(result) { NetworkDisconnectSA(handle); } }while(result == SLP_NETWORK_ERROR); FINISHED: if(buf) free(buf); return result; }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvDeReg(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { int sock; struct sockaddr_storage peeraddr; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; #ifdef ENABLE_SLPv2_SECURITY int urlauthlen = 0; unsigned char* urlauth = 0; if(SLPPropertyAsBoolean(SLPGetProperty("net.slp.securityEnabled"))) { result = SLPAuthSignUrl(handle->hspi, 0, 0, handle->params.dereg.urllen, handle->params.dereg.url, &urlauthlen, &urlauth); bufsize += urlauthlen; } #endif /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVDEREG */ /*-------------------------------------------------------------------*/ bufsize += handle->params.dereg.scopelistlen + 2; /* 2 bytes for len field*/ bufsize += handle->params.dereg.urllen + 6; /* 1 byte for reserved */ /* 2 bytes for lifetime */ /* 2 bytes for urllen */ /* 1 byte for authcount */ bufsize += 2; /* 2 bytes for taglistlen*/ /*--------------------------------------------*/ /* Allocate a buffer for the SRVDEREG message */ /*--------------------------------------------*/ buf = curpos = (char*)xmalloc(bufsize); if(buf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVDEREG*/ /*------------------------------------------------------------*/ /* scope list */ ToUINT16(curpos,handle->params.dereg.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.dereg.scopelist, handle->params.dereg.scopelistlen); curpos = curpos + handle->params.dereg.scopelistlen; /* url-entry reserved */ *curpos = 0; curpos = curpos + 1; /* url-entry lifetime */ ToUINT16(curpos, 0); curpos = curpos + 2; /* url-entry urllen */ ToUINT16(curpos,handle->params.dereg.urllen); curpos = curpos + 2; /* url-entry url */ memcpy(curpos, handle->params.dereg.url, handle->params.dereg.urllen); curpos = curpos + handle->params.dereg.urllen; /* url-entry authcount */ #ifdef ENABLE_SLPv2_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; } /* tag list */ /* TODO: No tag list for now put in taglist stuff */ ToUINT16(curpos,0); /*--------------------------*/ /* Call the RqstRply engine */ /*--------------------------*/ sock = NetworkConnectToSA(handle, handle->params.reg.scopelist, handle->params.reg.scopelistlen, &peeraddr); if(sock >= 0) { result = NetworkRqstRply(sock, &peeraddr, handle->langtag, 0, buf, SLP_FUNCT_SRVDEREG, bufsize, CallbackSrvDeReg, handle); if (result) { NetworkDisconnectSA(handle); } } else { result = SLP_NETWORK_INIT_FAILED; goto FINISHED; } FINISHED: if(buf) xfree(buf); #ifdef ENABLE_SLPv2_SECURITY if(urlauth) xfree(urlauth); #endif return result; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvReg(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer recvbuf, SLPBuffer* sendbuf, int errorcode) /* */ /* Returns: non-zero if message should be silently dropped */ /*-------------------------------------------------------------------------*/ { SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code also do not process mcast */ /* srvreg or srvdereg messages */ /*--------------------------------------------------------------*/ if (errorcode || message->header.flags & SLP_FLAG_MCAST) { goto RESPOND; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if (SLPIntersectStringList(message->body.srvreg.scopelistlen, message->body.srvreg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*---------------------------------*/ /* put the service in the database */ /*---------------------------------*/ if (ISLOCAL(message->peer.sin_addr)) { message->body.srvreg.source= SLP_REG_SOURCE_LOCAL; } else { message->body.srvreg.source = SLP_REG_SOURCE_REMOTE; } errorcode = SLPDDatabaseReg(message,recvbuf); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*--------------------------------------------------------------------*/ /* don't send back reply anything multicast SrvReg (set result empty) */ /*--------------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { result->end = result->start; goto FINISHED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result, 14); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT16(result->start + 2, 14); /*flags - TODO set the flags correctly */ *(result->start + 4) = 0; /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 12, errorcode); FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { int i; int urllen; int size = 0; SLPDDatabaseSrvRqstResult* db = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code */ /*--------------------------------------------------------------*/ if (errorcode) { goto RESPOND; } /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if (SLPIntersectStringList(message->body.srvrqst.prlistlen, message->body.srvrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------------------*/ /* Check to to see if a this is a special SrvRqst */ /*------------------------------------------------*/ if (SLPCompareString(message->body.srvrqst.srvtypelen, message->body.srvrqst.srvtype, 15, "directory-agent") == 0) { errorcode = v1ProcessDASrvRqst(peeraddr, message, sendbuf, errorcode); return errorcode; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if (SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*-------------------------------*/ /* Find services in the database */ /*-------------------------------*/ errorcode = SLPDDatabaseSrvRqstStart(message, &db); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { if (errorcode != 0 || db->urlcount == 0) { result->end = result->start; goto FINISHED; } } /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for url count */ if (errorcode == 0) { for (i = 0; i < db->urlcount; i++) { urllen = INT_MAX; errorcode = SLPv1ToEncoding(0, &urllen, message->header.encoding, db->urlarray[i]->url, db->urlarray[i]->urllen); if (errorcode) break; size += urllen + 4; /* 2 bytes for lifetime, 2 bytes for urllen */ } result = SLPBufferRealloc(result,size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; } } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVRPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-------------------------*/ /* Add rest of the SrvRply */ /*-------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; if (errorcode == 0) { /* urlentry count */ ToUINT16(result->curpos, db->urlcount); result->curpos = result->curpos + 2; for (i = 0; i < db->urlcount; i++) { /* url-entry lifetime */ ToUINT16(result->curpos, db->urlarray[i]->lifetime); result->curpos = result->curpos + 2; /* url-entry url and urllen */ urllen = size; errorcode = SLPv1ToEncoding(result->curpos + 2, &urllen, message->header.encoding, db->urlarray[i]->url, db->urlarray[i]->urllen); ToUINT16(result->curpos, urllen); result->curpos = result->curpos + 2 + urllen; } } else { /* urlentry count */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; } FINISHED: SLPDDatabaseSrvRqstEnd(db); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvTypeRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { int i, typelen; int size = 0; int count = 0; int found = 0; SLPDDatabaseSrvType* srvtypearray = 0; SLPBuffer result = *sendbuf; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPIntersectStringList(message->body.srvtyperqst.prlistlen, message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------------------------------------*/ if(SLPIntersectStringList(message->body.srvtyperqst.scopelistlen, message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*------------------------------------*/ /* Find service types in the database */ /*------------------------------------*/ while(found == count) { count += G_SlpdProperty.maxResults; if(srvtypearray) free(srvtypearray); srvtypearray = (SLPDDatabaseSrvType*)malloc(sizeof(SLPDDatabaseSrvType) * count); if(srvtypearray == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } found = SLPDDatabaseFindType(&(message->body.srvtyperqst), srvtypearray, count); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } } /* remember the amount found if is really big for next time */ if(found > G_SlpdProperty.maxResults) { G_SlpdProperty.maxResults = found; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST) { if(found == 0 || errorcode != 0) { result->end = result->start; goto FINISHED; } } /*-----------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvtyperply */ /*-----------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for srvtype count */ if(errorcode == 0) { for(i=0;i<found;i++) { typelen = INT_MAX; errorcode = SLPv1ToEncoding(0, &typelen, message->header.encoding, srvtypearray[i].type, srvtypearray[i].typelen); if(errorcode) break; size += typelen + 2; /* 2 byte for length */ } } result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVTYPERPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-----------------------------*/ /* Add rest of the SrvTypeRply */ /*-----------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos += 2; /* service type count */ ToUINT16(result->curpos, found); result->curpos += 2; /* TODO - make sure we don't return generic types */ for(i=0;i<found;i++) { typelen = size; SLPv1ToEncoding(result->curpos + 2, &typelen, message->header.encoding, srvtypearray[i].type, srvtypearray[i].typelen); ToUINT16(result->curpos, srvtypearray[i].typelen); result->curpos += 2 + typelen; } FINISHED: if(srvtypearray) free(srvtypearray); *sendbuf = result; return errorcode; }
/*=========================================================================*/ SLPError NetworkRqstRply(int sock, struct sockaddr_in* destaddr, const char* langtag, char* buf, char buftype, int bufsize, NetworkRqstRplyCallback callback, void * cookie) /* Transmits and receives SLP messages via multicast convergence algorithm */ /* */ /* Returns - SLP_OK on success */ /*=========================================================================*/ { struct timeval timeout; struct sockaddr_in peeraddr; SLPBuffer sendbuf = 0; SLPBuffer recvbuf = 0; SLPMessage msg = 0; SLPError result = 0; #ifdef WIN32 /* on WIN32 setsockopt takes a const char * argument */ char socktype = 0; #else int socktype = 0; #endif int langtaglen = 0; int prlistlen = 0; char* prlist = 0; int xid = 0; int mtu = 0; int size = 0; int xmitcount = 0; int rplycount = 0; int maxwait = 0; int totaltimeout = 0; int timeouts[MAX_RETRANSMITS]; /*----------------------------------------------------*/ /* Save off a few things we don't want to recalculate */ /*----------------------------------------------------*/ langtaglen = strlen(langtag); xid = SLPXidGenerate(); mtu = SLPPropertyAsInteger(SLPGetProperty("net.slp.MTU")); sendbuf = SLPBufferAlloc(mtu); if(sendbuf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto CLEANUP; } if(buftype == SLP_FUNCT_DASRVRQST) { /* do something special for SRVRQST that will be discovering DAs */ maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.DADiscovertTimeouts"), timeouts, MAX_RETRANSMITS ); /* SLP_FUNCT_DASRVRQST is a fake function. We really want to */ /* send a SRVRQST */ buftype = SLP_FUNCT_SRVRQST; } /* Figure unicast/multicast,TCP/UDP, wait and time out stuff */ if(ntohl(destaddr->sin_addr.s_addr) > 0xe0000000) { /* Multicast or broadcast */ maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.multicastMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.multicastTimeouts"), timeouts, MAX_RETRANSMITS ); socktype = SOCK_DGRAM; xmitcount = 0; } else { maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.unicastMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.unicastTimeouts"), timeouts, MAX_RETRANSMITS ); size = sizeof(socktype); getsockopt(sock,SOL_SOCKET,SO_TYPE,&socktype,&size); socktype = SOCK_STREAM; xmitcount = MAX_RETRANSMITS; } /*--------------------------------*/ /* Allocate memory for the prlist */ /*--------------------------------*/ prlist = (char*)malloc(mtu); if(prlist == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto CLEANUP; } *prlist = 0; prlistlen = 0; /*--------------------------*/ /* Main retransmission loop */ /*--------------------------*/ while(xmitcount <= MAX_RETRANSMITS) { xmitcount++; /*--------------------*/ /* setup recv timeout */ /*--------------------*/ if(socktype == SOCK_DGRAM) { totaltimeout += timeouts[xmitcount]; if(totaltimeout >= maxwait || timeouts[xmitcount] == 0) { /* we are all done */ break; } timeout.tv_sec = timeouts[xmitcount] / 1000; timeout.tv_usec = (timeouts[xmitcount] % 1000) * 1000; } else { timeout.tv_sec = maxwait / 1000; timeout.tv_usec = (maxwait % 1000) * 1000; } size = 14 + langtaglen + 2 + prlistlen + bufsize; if(SLPBufferRealloc(sendbuf,size) == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto CLEANUP; } /*-----------------------------------*/ /* Add the header to the send buffer */ /*-----------------------------------*/ /*version*/ *(sendbuf->start) = 2; /*function id*/ *(sendbuf->start + 1) = buftype; /*length*/ ToUINT24(sendbuf->start + 2, size); /*flags*/ ToUINT16(sendbuf->start + 5, socktype == SOCK_STREAM ? 0 : SLP_FLAG_MCAST); /*ext offset*/ ToUINT24(sendbuf->start + 7,0); /*xid*/ ToUINT16(sendbuf->start + 10,xid); /*lang tag len*/ ToUINT16(sendbuf->start + 12,langtaglen); /*lang tag*/ memcpy(sendbuf->start + 14, langtag, langtaglen); sendbuf->curpos = sendbuf->start + langtaglen + 14 ; /*-----------------------------------*/ /* Add the prlist to the send buffer */ /*-----------------------------------*/ if( buftype == SLP_FUNCT_SRVRQST || buftype == SLP_FUNCT_ATTRRQST || buftype == SLP_FUNCT_SRVTYPERQST) { ToUINT16(sendbuf->curpos,prlistlen); sendbuf->curpos = sendbuf->curpos + 2; memcpy(sendbuf->curpos, prlist, prlistlen); sendbuf->curpos = sendbuf->curpos + prlistlen; } /*-----------------------------*/ /* Add the rest of the message */ /*-----------------------------*/ memcpy(sendbuf->curpos, buf, bufsize); /*----------------------*/ /* send the send buffer */ /*----------------------*/ result = SLPNetworkSendMessage(sock, sendbuf, destaddr, &timeout); if(result != 0) { /* we could not send the message for some reason */ /* we're done */ result = SLP_NETWORK_ERROR; goto FINISHED; } /*----------------*/ /* Main recv loop */ /*----------------*/ while(1) { if(SLPNetworkRecvMessage(sock, &recvbuf, &peeraddr, &timeout) != 0) { /* An error occured while receiving the message */ /* probably a just time out error. Retry send. */ break; } /* Parse the message and call callback */ msg = SLPMessageRealloc(msg); if(msg == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } if(SLPMessageParseBuffer(recvbuf, msg) == 0) { if (msg->header.xid == xid) { rplycount = rplycount + 1; if(callback(result, msg, cookie) == 0) { goto CLEANUP; } } } if(socktype == SOCK_STREAM) { goto FINISHED; } /* add the peer to the previous responder list */ if(prlistlen != 0) { strcat(prlist,","); } strcat(prlist,inet_ntoa(peeraddr.sin_addr)); prlistlen = strlen(prlist); } } FINISHED: /*----------------*/ /* We're all done */ /*----------------*/ if(rplycount == 0) { result = SLP_NETWORK_TIMED_OUT; } /*-------------------------------------*/ /* Notify the callback that we're done */ /*-------------------------------------*/ callback(SLP_LAST_CALL,msg,cookie); /*----------------*/ /* Free resources */ /*----------------*/ CLEANUP: if(prlist) free(prlist); SLPBufferFree(sendbuf); SLPBufferFree(recvbuf); SLPMessageFree(msg); close(sock); return result; }
/*-------------------------------------------------------------------------*/ void ProcessSASrvRqst(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int size = 0; if(message->body.srvrqst.scopelistlen == 0 || SLPStringListIntersect(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0 ) { /*----------------------*/ /* Send back a SAAdvert */ /*----------------------*/ /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 21; /* 14 bytes for header */ /* 2 bytes for url count */ /* 2 bytes for scope list len */ /* 2 bytes for attr list len */ /* 1 byte for authblock count */ size += G_SlpdProperty.myUrlLen; size += G_SlpdProperty.useScopesLen; /* TODO: size += G_SlpdProperty.SAAttributes */ result = SLPBufferRealloc(result,size); if(result == 0) { /* TODO: out of memory, what should we do here! */ return; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SAADVERT; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*--------------------------*/ /* Add rest of the SAAdvert */ /*--------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* url len */ ToUINT16(result->curpos, G_SlpdProperty.myUrlLen); result->curpos = result->curpos + 2; /* url */ memcpy(result->start,G_SlpdProperty.myUrl,G_SlpdProperty.myUrlLen); result->curpos = result->curpos + G_SlpdProperty.myUrlLen; /* scope list len */ ToUINT16(result->curpos, G_SlpdProperty.useScopesLen); result->curpos = result->curpos + 2; /* scope list */ memcpy(result->start,G_SlpdProperty.useScopes,G_SlpdProperty.useScopesLen); result->curpos = result->curpos + G_SlpdProperty.useScopesLen; /* attr list len */ /* ToUINT16(result->curpos,G_SlpdProperty.SAAttributesLen) */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; /* attr list */ /* memcpy(result->start,G_SlpdProperty.SAAttributes,G_SlpdProperty.SAAttributesLen) */ /* authblock count */ *(result->curpos) = 0; } else { /*--------------------------------*/ /* Send back a SrvRply with error */ /*--------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST) { /* drop multicast SrvRqsts we can not answer */ result->end = result->start; } else { /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for url count */ result = SLPBufferRealloc(result,size); if(result == 0) { /* TODO: out of memory, what should we do here! */ return; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVRPLY; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------------*/ /* Add rest of the SrvRply */ /*-------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, SLP_ERROR_SCOPE_NOT_SUPPORTED); result->curpos = result->curpos + 2; /* urlentry count */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; } } }
/*-------------------------------------------------------------------------*/ void ProcessSrvRqstError(SLPMessage message, SLPBuffer result, int errorcode) /*-------------------------------------------------------------------------*/ { int size; /*--------------------------------*/ /* Send back a SrvRply with error */ /*--------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST) { /* drop multicast SrvRqsts we can not answer */ result->end = result->start; } else { /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for url count */ result = SLPBufferRealloc(result,size); if(result == 0) { /* TODO: out of memory, should we do anything else here! */ result->end = result->start; return; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVRPLY; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*------------------------------------------*/ /* Add rest of the SrvRply (with errorcode) */ /*------------------------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; /* urlentry count */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; } }
/*-------------------------------------------------------------------------*/ void ProcessDASrvRqst(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int size = 0; if(G_SlpdProperty.isDA == 0) { /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST) { result->end = result->start; return; } ProcessSrvRqstError(message, result, SLP_ERROR_MESSAGE_NOT_SUPPORTED); return; } if(message->body.srvrqst.scopelistlen == 0 || SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0 ) { /*----------------------*/ /* Send back a DAAdvert */ /*----------------------*/ /* increment the value for DATimestamp */ G_SlpdProperty.DATimestamp += 1; if(G_SlpdProperty.DATimestamp == 0) { G_SlpdProperty.DATimestamp = 1; } /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 29; /* 14 bytes for header */ /* 2 errorcode */ /* 4 bytes for timestamp */ /* 2 bytes for url len */ /* 2 bytes for scope list len */ /* 2 bytes for attr list len */ /* 2 bytes for spi str len */ /* 1 byte for authblock count */ size += G_SlpdProperty.myUrlLen; size += G_SlpdProperty.useScopesLen; /* TODO: - we don't use attributes yet */ /* size += G_SlpdProperty.SAAttributes; */ result = SLPBufferRealloc(result,size); if(result == 0) { /* TODO: out of memory, what should we do here! */ return; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_DAADVERT; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*--------------------------*/ /* Add rest of the DAAdvert */ /*--------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code */ ToUINT16(result->curpos,0); result->curpos = result->curpos + 2; /* timestamp */ ToUINT32(result->curpos,G_SlpdProperty.DATimestamp); result->curpos = result->curpos + 4; /* url len */ ToUINT16(result->curpos, G_SlpdProperty.myUrlLen); result->curpos = result->curpos + 2; /* url */ memcpy(result->curpos,G_SlpdProperty.myUrl,G_SlpdProperty.myUrlLen); result->curpos = result->curpos + G_SlpdProperty.myUrlLen; /* scope list len */ ToUINT16(result->curpos, G_SlpdProperty.useScopesLen); result->curpos = result->curpos + 2; /* scope list */ memcpy(result->curpos,G_SlpdProperty.useScopes,G_SlpdProperty.useScopesLen); result->curpos = result->curpos + G_SlpdProperty.useScopesLen; /* attr list len */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; /* attr list */ /* memcpy(result->start,G_SlpdProperty.DAAttributes,G_SlpdProperty.DAAttributesLen) */ /* result->curpos = result->curpos + G_SlpdProperty.DAAttributesLen */ /* SPI List */ ToUINT16(result->curpos,0); result->curpos = result->curpos + 2; /* authblock count */ *(result->curpos) = 0; result->curpos = result->curpos + 1; } else { ProcessSrvRqstError(message, result, SLP_ERROR_SCOPE_NOT_SUPPORTED); } }
/*-------------------------------------------------------------------------*/ int ProcessSrvTypeRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { int i; int size = 0; int count = 0; int found = 0; SLPDDatabaseSrvType* srvtypearray = 0; SLPBuffer result = *sendbuf; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPIntersectStringList(message->body.srvtyperqst.prlistlen, message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /* TODO: check the spi list of the message and return */ /* AUTHENTICATION_UNKNOWN since we do not do authentication yet */ /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPIntersectStringList(message->body.srvtyperqst.scopelistlen, message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*------------------------------------*/ /* Find service types in the database */ /*------------------------------------*/ while(found == count) { count += G_SlpdProperty.maxResults; if(srvtypearray) free(srvtypearray); srvtypearray = (SLPDDatabaseSrvType*)malloc(sizeof(SLPDDatabaseSrvType) * count); if(srvtypearray == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } found = SLPDDatabaseFindType(&(message->body.srvtyperqst), srvtypearray, count); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } } /* remember the amount found if is really big for next time */ if(found > G_SlpdProperty.maxResults) { G_SlpdProperty.maxResults = found; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(found == 0 || errorcode != 0) { if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { result->end = result->start; goto FINISHED; } } /*-----------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvtyperply */ /*-----------------------------------------------------------------*/ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for srvtype list length */ for(i=0;i<found;i++) { size += srvtypearray[i].typelen + 1; /* 1 byte for comma */ } if(found) size--; /* remove the extra comma */ result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVTYPERPLY; /*length*/ ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-----------------------------*/ /* Add rest of the SrvTypeRply */ /*-----------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos += 2; /* length of srvtype-list */ ToUINT16(result->curpos, size - (message->header.langtaglen + 18)); result->curpos += 2; if(errorcode == 0) { for(i=0;i<found;i++) { memcpy(result->curpos, srvtypearray[i].type, srvtypearray[i].typelen); result->curpos += srvtypearray[i].typelen; if(i < found - 1) *result->curpos++ = ','; } } FINISHED: if(srvtypearray) free(srvtypearray); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ SLPError ProcessSrvTypeRqst(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { int sock; struct sockaddr_in peeraddr; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; /*-------------------------------------------------------------------*/ /* determine the size of the fixed portion of the SRVTYPERQST */ /*-------------------------------------------------------------------*/ bufsize = handle->params.findsrvtypes.namingauthlen + 2; /* 2 bytes for len field */ bufsize += handle->params.findsrvtypes.scopelistlen + 2; /* 2 bytes for len field */ /* TODO: make sure that we don't exceed the MTU */ buf = curpos = (char*)xmalloc(bufsize); if(buf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*----------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVTYPERQST */ /*----------------------------------------------------------------*/ /* naming authority */ if(strcmp(handle->params.findsrvtypes.namingauth, "*") == 0) { ToUINT16(curpos,0xffff); /* 0xffff indicates all service types */ curpos += 2; bufsize--; /* '*' is not put on the wire */ } else { ToUINT16(curpos,handle->params.findsrvtypes.namingauthlen); curpos += 2; memcpy(curpos, handle->params.findsrvtypes.namingauth, handle->params.findsrvtypes.namingauthlen); curpos += handle->params.findsrvtypes.namingauthlen; } /* scope list */ ToUINT16(curpos,handle->params.findsrvtypes.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.findsrvtypes.scopelist, handle->params.findsrvtypes.scopelistlen); curpos = curpos + handle->params.findsrvtypes.scopelistlen; /*--------------------------*/ /* Call the RqstRply engine */ /*--------------------------*/ do { sock = NetworkConnectToDA(handle, handle->params.findsrvtypes.scopelist, handle->params.findsrvtypes.scopelistlen, &peeraddr); if(sock == -1) { /* use multicast as a last resort */ result = NetworkMcastRqstRply(handle->langtag, buf, SLP_FUNCT_SRVTYPERQST, bufsize, ProcessSrvTypeRplyCallback, handle); break; } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, 0, buf, SLP_FUNCT_SRVTYPERQST, bufsize, ProcessSrvTypeRplyCallback, handle); if(result) { NetworkDisconnectDA(handle); } }while(result == SLP_NETWORK_ERROR); FINISHED: if(buf) xfree(buf); return result; }
/*-------------------------------------------------------------------------*/ int v1ProcessAttrRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { SLPDDatabaseAttrRqstResult* db = 0; int attrlen = 0; int size = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code */ /*--------------------------------------------------------------*/ if (errorcode) { goto RESPOND; } /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if (SLPIntersectStringList(message->body.attrrqst.prlistlen, message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if (SLPIntersectStringList(message->body.attrrqst.scopelistlen, message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*---------------------------------*/ /* Find attributes in the database */ /*---------------------------------*/ errorcode = SLPDDatabaseAttrRqstStart(message,&db); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { if (errorcode != 0 || db->attrlistlen == 0) { result->end = result->start; goto FINISHED; } } /*--------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole attrrply */ /*--------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for attr-list len */ if (errorcode == 0) { attrlen = INT_MAX; errorcode = SLPv1ToEncoding(0, &attrlen, message->header.encoding, db->attrlist, db->attrlistlen); size += attrlen; } /*-------------------*/ /* Alloc the buffer */ /*-------------------*/ result = SLPBufferRealloc(result,size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_ATTRRPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*--------------------------*/ /* Add rest of the AttrRply */ /*--------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; if (errorcode == 0) { /* attr-list len */ ToUINT16(result->curpos, attrlen); result->curpos = result->curpos + 2; attrlen = size; SLPv1ToEncoding(result->curpos, &attrlen, message->header.encoding, db->attrlist, db->attrlistlen); result->curpos = result->curpos + attrlen; } FINISHED: *sendbuf = result; if (db) SLPDDatabaseAttrRqstEnd(db); return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvTypeRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { char* type; char* end; char* slider; int i; int typelen; int numsrvtypes = 0; int size = 0; SLPDDatabaseSrvTypeRqstResult* db = 0; SLPBuffer result = *sendbuf; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen, message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------------------------------------*/ if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen, message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*------------------------------------*/ /* Find service types in the database */ /*------------------------------------*/ errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { if (errorcode != 0 || db->srvtypelistlen == 0) { result->end = result->start; goto FINISHED; } } /*-----------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvtyperply */ /*-----------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for num of service types */ if (errorcode == 0) { if (db->srvtypelistlen) { /* there has to be at least one service type*/ numsrvtypes = 1; /* count the rest of the service types */ type = db->srvtypelist; for (i=0; i< db->srvtypelistlen; i++) { if (type[i] == ',') { numsrvtypes += 1; } } /* figure out how much memory is required for srvtype strings */ typelen = INT_MAX; errorcode = SLPv1ToEncoding(0, &typelen, message->header.encoding, db->srvtypelist, db->srvtypelistlen); /* TRICKY: we add in the numofsrvtypes + 1 to make room for the */ /* type length. We can do this because the ',' of the comma */ /* delimited list is one byte. */ size = size + typelen + numsrvtypes + 1; } else { numsrvtypes = 0; } } /*-----------------*/ /* Allocate memory */ /*-----------------*/ result = SLPBufferRealloc(result,size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVTYPERPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-----------------------------*/ /* Add rest of the SrvTypeRply */ /*-----------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos += 2; if (errorcode == 0) { /* num of service types */ ToUINT16(result->curpos, numsrvtypes); result->curpos += 2; /* service type strings */ type = db->srvtypelist; slider = db->srvtypelist; end = &(type[db->srvtypelistlen]); for (i=0;i<numsrvtypes; i++) { while (slider < end && *slider != ',') slider++; typelen = size; /* put in the encoded service type */ SLPv1ToEncoding(result->curpos + 2, &typelen, message->header.encoding, type, slider - type); /* slip in the typelen */ ToUINT16(result->curpos, typelen); result->curpos += 2; result->curpos += typelen; slider ++; /* skip comma */ type = slider; } /* TODO - make sure we don't return generic types */ } FINISHED: if (db) SLPDDatabaseSrvTypeRqstEnd(db); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ SLPError ProcessAttrRqst(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { int sock; struct sockaddr_in peeraddr; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; #ifdef ENABLE_SLPv2_SECURITY int spistrlen = 0; char* spistr = 0; 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 ATTRRQST */ /*-------------------------------------------------------------------*/ bufsize = handle->params.findattrs.urllen + 2; /* 2 bytes for len field */ bufsize += handle->params.findattrs.scopelistlen + 2; /* 2 bytes for len field */ bufsize += handle->params.findattrs.taglistlen + 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 ATTRRQST*/ /*------------------------------------------------------------*/ /* url */ ToUINT16(curpos,handle->params.findattrs.urllen); curpos = curpos + 2; memcpy(curpos, handle->params.findattrs.url, handle->params.findattrs.urllen); curpos = curpos + handle->params.findattrs.urllen; /* scope list */ ToUINT16(curpos,handle->params.findattrs.scopelistlen); curpos = curpos + 2; memcpy(curpos, handle->params.findattrs.scopelist, handle->params.findattrs.scopelistlen); curpos = curpos + handle->params.findattrs.scopelistlen; /* taglist */ ToUINT16(curpos,handle->params.findattrs.taglistlen); curpos = curpos + 2; memcpy(curpos, handle->params.findattrs.taglist, handle->params.findattrs.taglistlen); curpos = curpos + handle->params.findattrs.taglistlen; #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 { sock = NetworkConnectToDA(handle, handle->params.findattrs.scopelist, handle->params.findattrs.scopelistlen, &peeraddr); if(sock == -1) { /* use multicast as a last resort */ result = NetworkMcastRqstRply(handle->langtag, buf, SLP_FUNCT_ATTRRQST, bufsize, ProcessAttrRplyCallback, handle); break; } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, 0, buf, SLP_FUNCT_ATTRRQST, bufsize, ProcessAttrRplyCallback, 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; }
/*=========================================================================*/ void SLPDKnownDAActiveDiscovery() /* Set outgoing socket list to send an active DA discovery SrvRqst */ /* */ /* Returns: none */ /*=========================================================================*/ { size_t bufsize; SLPDAEntry* daentry; SLPDSocket* sock; char* prlist; size_t prlistlen; struct in_addr peeraddr; if(G_SlpdProperty.isDA) { /* do not perform active DA discovery if we are a DA */ return; } if(G_SlpdProperty.activeDiscoveryAttempts <= 0) { return; } G_SlpdProperty.activeDiscoveryAttempts --; /*--------------------------------------------------*/ /* Create new DATAGRAM socket with appropriate peer */ /*--------------------------------------------------*/ if(G_SlpdProperty.isBroadcastOnly == 0) { peeraddr.s_addr = htonl(SLP_MCAST_ADDRESS); sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST); } else { peeraddr.s_addr = htonl(SLP_BCAST_ADDRESS); sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST); } /*-------------------------------------------------*/ /* Generate a DA service request buffer to be sent */ /*-------------------------------------------------*/ /* determine the size of the fixed portion of the SRVRQST */ bufsize = 47; /* 14 bytes for the header */ /* 2 bytes for the prlistlen */ /* 2 bytes for the srvtype length */ /* 23 bytes for "service:directory-agent" srvtype */ /* 2 bytes for scopelistlen */ /* 2 bytes for predicatelen */ /* 2 bytes for sprstrlen */ /* figure out what our Prlist will be by going through our list of */ /* known DAs */ prlistlen = 0; prlist = malloc(SLP_MAX_DATAGRAM_SIZE); if(prlist == 0) { goto FINISHED; } *prlist = 0; daentry = (SLPDAEntry*)G_KnownDAList.head; while(daentry && prlistlen < SLP_MAX_DATAGRAM_SIZE) { strcat(prlist,inet_ntoa(daentry->daaddr)); daentry = (SLPDAEntry*)daentry->listitem.next; if(daentry) { strcat(prlist,","); } prlistlen = strlen(prlist); } /* Allocate the send buffer */ bufsize += G_SlpdProperty.localeLen + prlistlen; sock->sendbuf = SLPBufferRealloc(sock->sendbuf,bufsize); if(sock->sendbuf == 0) { return; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVRQST */ /*------------------------------------------------------------*/ /*version*/ *(sock->sendbuf->start) = 2; /*function id*/ *(sock->sendbuf->start + 1) = SLP_FUNCT_SRVRQST; /*length*/ ToUINT24(sock->sendbuf->start + 2, bufsize); /*flags*/ ToUINT16(sock->sendbuf->start + 5, SLP_FLAG_MCAST); /*ext offset*/ ToUINT24(sock->sendbuf->start + 7,0); /*xid*/ ToUINT16(sock->sendbuf->start + 10, 0); /* TODO: generat a real XID */ /*lang tag len*/ ToUINT16(sock->sendbuf->start + 12, G_SlpdProperty.localeLen); /*lang tag*/ memcpy(sock->sendbuf->start + 14, G_SlpdProperty.locale, G_SlpdProperty.localeLen); sock->sendbuf->curpos = sock->sendbuf->start + G_SlpdProperty.localeLen + 14; /* Prlist */ ToUINT16(sock->sendbuf->curpos,prlistlen); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; memcpy(sock->sendbuf->curpos,prlist,prlistlen); sock->sendbuf->curpos = sock->sendbuf->curpos + prlistlen; /* service type */ ToUINT16(sock->sendbuf->curpos,23); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; memcpy(sock->sendbuf->curpos,"service:directory-agent",23); sock->sendbuf->curpos = sock->sendbuf->curpos + 23; /* scope list zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /* predicate zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /* spi list zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /*------------------------------------*/ /* Send the active DA service request */ /*------------------------------------*/ if(sock) { sendto(sock->fd, sock->sendbuf->start, sock->sendbuf->end - sock->sendbuf->start, 0, &(sock->peerinfo.peeraddr), sock->peerinfo.peeraddrlen); } FINISHED: SLPDSocketFree(sock); }
/*-------------------------------------------------------------------------*/ int ProcessSrvRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { int i; int size = 0; int count = 0; int found = 0; SLPDDatabaseSrvUrl* srvarray = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code */ /*--------------------------------------------------------------*/ if(errorcode) { goto RESPOND; } /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPIntersectStringList(message->body.srvrqst.prlistlen, message->body.srvrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------------------*/ /* Check to to see if a this is a special SrvRqst */ /*------------------------------------------------*/ if(SLPCompareString(message->body.srvrqst.srvtypelen, message->body.srvrqst.srvtype, 23, "service:directory-agent") == 0) { errorcode = ProcessDASrvRqst(peeraddr, message, sendbuf, errorcode); return errorcode; } if(SLPCompareString(message->body.srvrqst.srvtypelen, message->body.srvrqst.srvtype, 21, "service:service-agent") == 0) { errorcode = ProcessSASrvRqst(peeraddr, message, sendbuf, errorcode); return errorcode; } /* TODO: check the spi list of the message and return */ /* AUTHENTICATION_UNKNOWN since we do not do authentication yet */ /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*-------------------------------*/ /* Find services in the database */ /*-------------------------------*/ while(found == count) { count += G_SlpdProperty.maxResults; if(srvarray) free(srvarray); srvarray = (SLPDDatabaseSrvUrl*)malloc(sizeof(SLPDDatabaseSrvUrl) * count); if(srvarray == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } found = SLPDDatabaseFindSrv(&(message->body.srvrqst), srvarray, count); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } } /* remember the amount found if is really big for next time */ if(found > G_SlpdProperty.maxResults) { G_SlpdProperty.maxResults = found; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(found == 0 || errorcode != 0) { if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { result->end = result->start; goto FINISHED; } } /*-------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvrply */ /*-------------------------------------------------------------*/ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for url count */ if(errorcode == 0) { for(i=0;i<found;i++) { size += srvarray[i].urllen + 6; /* 1 byte for reserved */ /* 2 bytes for lifetime */ /* 2 bytes for urllen */ /* 1 byte for authcount */ /* TODO: Fix this for authentication */ } result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVRPLY; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------------*/ /* Add rest of the SrvRply */ /*-------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; /* urlentry count */ ToUINT16(result->curpos, found); result->curpos = result->curpos + 2; for(i=0;i<found;i++) { /* url-entry reserved */ *result->curpos = 0; result->curpos = result->curpos + 1; /* url-entry lifetime */ ToUINT16(result->curpos,srvarray[i].lifetime); result->curpos = result->curpos + 2; /* url-entry urllen */ ToUINT16(result->curpos,srvarray[i].urllen); result->curpos = result->curpos + 2; /* url-entry url */ memcpy(result->curpos,srvarray[i].url,srvarray[i].urllen); result->curpos = result->curpos + srvarray[i].urllen; /* url-entry authcount */ *result->curpos = 0; result->curpos = result->curpos + 1; /* TODO: put in authentication stuff too */ } FINISHED: if(srvarray) free(srvarray); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ 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; }
/*-------------------------------------------------------------------------*/ int ProcessSASrvRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { int size = 0; SLPBuffer result = *sendbuf; if(message->body.srvrqst.scopelistlen == 0 || SLPIntersectStringList(message->body.srvrqst.scopelistlen, message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*----------------------*/ /* Send back a SAAdvert */ /*----------------------*/ /*--------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole SAAdvert */ /*--------------------------------------------------------------*/ size = message->header.langtaglen + 21; /* 14 bytes for header */ /* 2 bytes for url count */ /* 2 bytes for scope list len */ /* 2 bytes for attr list len */ /* 1 byte for authblock count */ size += G_SlpdProperty.myUrlLen; size += G_SlpdProperty.useScopesLen; /* TODO: size += G_SlpdProperty.SAAttributes */ result = SLPBufferRealloc(result,size); if(result == 0) { /* TODO: out of memory, what should we do here! */ errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SAADVERT; /*length*/ ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*--------------------------*/ /* Add rest of the SAAdvert */ /*--------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* url len */ ToUINT16(result->curpos, G_SlpdProperty.myUrlLen); result->curpos = result->curpos + 2; /* url */ memcpy(result->curpos,G_SlpdProperty.myUrl,G_SlpdProperty.myUrlLen); result->curpos = result->curpos + G_SlpdProperty.myUrlLen; /* scope list len */ ToUINT16(result->curpos, G_SlpdProperty.useScopesLen); result->curpos = result->curpos + 2; /* scope list */ memcpy(result->curpos,G_SlpdProperty.useScopes,G_SlpdProperty.useScopesLen); result->curpos = result->curpos + G_SlpdProperty.useScopesLen; /* attr list len */ /* ToUINT16(result->curpos,G_SlpdProperty.SAAttributesLen) */ ToUINT16(result->curpos, 0); result->curpos = result->curpos + 2; /* attr list */ /* memcpy(result->start,G_SlpdProperty.SAAttributes,G_SlpdProperty.SAAttributesLen) */ /* authblock count */ *(result->curpos) = 0; } FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ 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; }
/*-------------------------------------------------------------------------*/ int ProcessSrvDeReg(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /* */ /* Returns: non-zero if message should be silently dropped */ /*-------------------------------------------------------------------------*/ { SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code also do not process mcast */ /* srvreg or srvdereg messages */ /*--------------------------------------------------------------*/ if(errorcode || message->header.flags & SLP_FLAG_MCAST) { goto RESPOND; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------------------------------------*/ if(SLPIntersectStringList(message->body.srvdereg.scopelistlen, message->body.srvdereg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*-------------------------------*/ /* TODO: Validate the authblocks */ /*-------------------------------*/ /*--------------------------------------*/ /* remove the service from the database */ /*--------------------------------------*/ if(SLPDDatabaseDeReg(&(message->body.srvdereg)) == 0) { errorcode = 0; } else { errorcode = SLP_ERROR_INTERNAL_ERROR; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*---------------------------------------------------------*/ /* don't do anything multicast SrvDeReg (set result empty) */ /*---------------------------------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { result->end = result->start; goto FINISHED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result,message->header.langtaglen + 16); if(result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT24(result->start + 2,message->header.langtaglen + 16); /*flags*/ ToUINT16(result->start + 5,0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 14 + message->header.langtaglen, errorcode); FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ void ProcessAttrRqst(SLPDPeerInfo* peerinfo, SLPMessage message, SLPBuffer result) /*-------------------------------------------------------------------------*/ { int i; int attrlistlen = 0; int size = 0; int count = 0; int found = 0; SLPDDatabaseAttr* attrarray = 0; int errorcode = 0; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPStringListIntersect(message->body.attrrqst.prlistlen, message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; return; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPStringListIntersect(message->body.attrrqst.scopelistlen, message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) == 0) { result->end = result->start; return; } /*-------------------------------*/ /* Find attributes in the database */ /*-------------------------------*/ while(found == count) { count += SLPDPROCESS_RESULT_COUNT; if(attrarray) free(attrarray); attrarray = (SLPDDatabaseAttr*)malloc(sizeof(SLPDDatabaseAttr) * count); if(attrarray == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } found = SLPDDatabaseFindAttr(&(message->body.attrrqst), attrarray, count); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; break; } } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(found <= 0 && (message->header.flags & SLP_FLAG_MCAST)) { if(attrarray) free(attrarray); result->end = result->start; return; } /*--------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole attrrply */ /*--------------------------------------------------------------*/ size = message->header.langtaglen + 20; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for attr-list len */ /* 2 bytes for the authblockcount */ for (i=0;i<found;i++) { attrlistlen += attrarray[i].attrlen; } size += attrlistlen; /*-------------------*/ /* Alloc the buffer */ /*-------------------*/ result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_ATTRRPLY; /*length*/ ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*--------------------------*/ /* Add rest of the AttrRqst */ /*--------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; /* attr-list len */ ToUINT16(result->curpos, attrlistlen); result->curpos = result->curpos + 2; for(i=0;i<found;i++) { memcpy(result->curpos,attrarray[i].attr,attrarray[i].attrlen); result->curpos = result->curpos + attrarray[i].attrlen; } /* TODO: no auth block */ ToUINT16(result->curpos, 0); if(attrarray) free(attrarray); }
/*-------------------------------------------------------------------------*/ int ProcessAttrRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { SLPDDatabaseAttr attr; int size = 0; int found = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code */ /*--------------------------------------------------------------*/ if(errorcode) { goto RESPOND; } /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if(SLPIntersectStringList(message->body.attrrqst.prlistlen, message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /* TODO: check the spi list of the message and return */ /* AUTHENTICATION_UNKNOWN since we do not do authentication yet */ /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPIntersectStringList(message->body.attrrqst.scopelistlen, message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*-------------------------------*/ /* Find attributes in the database */ /*-------------------------------*/ found = SLPDDatabaseFindAttr(&(message->body.attrrqst), &attr); if(found < 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if(found == 0 || errorcode != 0) { if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { result->end = result->start; goto FINISHED; } } /*--------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole attrrply */ /*--------------------------------------------------------------*/ size = message->header.langtaglen + 20; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for attr-list len */ /* 2 bytes for the authblockcount */ size += attr.attrlistlen; /*-------------------*/ /* Alloc the buffer */ /*-------------------*/ result = SLPBufferRealloc(result,size); if(result == 0) { found = 0; errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_ATTRRPLY; /*length*/ ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*--------------------------*/ /* Add rest of the AttrRqst */ /*--------------------------*/ result->curpos = result->start + 14 + message->header.langtaglen; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; /* attr-list len */ ToUINT16(result->curpos, attr.attrlistlen); result->curpos = result->curpos + 2; memcpy(result->curpos, attr.attrlist, attr.attrlistlen); result->curpos = result->curpos + attr.attrlistlen; /* TODO: no auth block */ ToUINT16(result->curpos, 0); FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ 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 ProcessSrvReg(PSLPHandleInfo handle) /*-------------------------------------------------------------------------*/ { struct sockaddr_in peeraddr; int sock = 0; int bufsize = 0; char* buf = 0; char* curpos = 0; SLPError result = 0; /*-------------------------------------------------------------------*/ /* 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 */ /* TODO: Fix this for authentication */ buf = curpos = (char*)malloc(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 authcount */ *curpos = 0; curpos = curpos + 1; /* TODO: put in urlentry authentication stuff too */ /* 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; /* attr auths*/ *(curpos) = 0; /*---------------------------------------*/ /* Connect to slpd or a DA */ /*---------------------------------------*/ sock = NetworkConnectToSlpd(&peeraddr); if(sock < 0) { sock = NetworkConnectToDA(handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen, &peeraddr); { result = SLP_NETWORK_INIT_FAILED; goto FINISHED; } } result = NetworkRqstRply(sock, &peeraddr, handle->langtag, buf, SLP_FUNCT_SRVREG, bufsize, CallbackSrvReg, handle); FINISHED: if(buf) free(buf); return result; }