/***************************************************************************/ /* */ /* Project: OpenSLP - OpenSource implementation of Service Location */ /* Protocol */ /* */ /* File: slp_message.h */ /* */ /* Abstract: Header file that defines structures and constants that are */ /* specific to the SLP wire protocol messages. */ /* */ /*-------------------------------------------------------------------------*/ /* */ /* Please submit patches to http://www.openslp.org */ /* */ /*-------------------------------------------------------------------------*/ /* */ /* Copyright (C) 2000 Caldera Systems, Inc */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in */ /* the documentation and/or other materials provided with the */ /* distribution. */ /* */ /* Neither the name of Caldera Systems nor the names of its */ /* contributors may be used to endorse or promote products derived */ /* from this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */ /* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* */ /***************************************************************************/ #include "slp_message.h" #include "slp_xmalloc.h" #ifndef _WIN32 #include #include #endif #if defined(ENABLE_SLPv1) #include #endif /*=========================================================================*/ int SLPMessageParseHeader(SLPBuffer buffer, SLPHeader* header) /* Fill out a header structure with what ever is in the buffer */ /* */ /* buffer (IN) the buffer to be parsed */ /* */ /* header (IN/OUT) pointer to the header structure to fill out */ /*=========================================================================*/ { if (buffer->end - buffer->start < 2) { return SLP_ERROR_PARSE_ERROR; } header->version = *(buffer->curpos); header->functionid = *(buffer->curpos + 1); if(header->version != 2) { return SLP_ERROR_VER_NOT_SUPPORTED; } /* check for invalid length 18 bytes is the smallest v2 message*/ if (buffer->end - buffer->start < 18) { return SLP_ERROR_PARSE_ERROR; } header->length = AsUINT24(buffer->curpos + 2); header->flags = AsUINT16(buffer->curpos + 5); header->encoding = 0; /* not used for SLPv2 */ header->extoffset = AsUINT24(buffer->curpos + 7); header->xid = AsUINT16(buffer->curpos + 10); header->langtaglen = AsUINT16(buffer->curpos + 12); header->langtag = buffer->curpos + 14; /* check for invalid function id */ if(header->functionid > SLP_FUNCT_SAADVERT) { return SLP_ERROR_PARSE_ERROR; } if(header->length != buffer->end - buffer->start) { return SLP_ERROR_PARSE_ERROR; } /* check for invalid flags */ if(header->flags & 0x1fff) { return SLP_ERROR_PARSE_ERROR; } buffer->curpos = buffer->curpos + header->langtaglen + 14; /* check for invalid langtaglen */ if((void*)(header->langtag + header->langtaglen) > (void*)buffer->end) { return SLP_ERROR_PARSE_ERROR; } /* check for invalid ext offset */ if(buffer->start + header->extoffset > buffer->end) { return SLP_ERROR_PARSE_ERROR; } return 0; } /*--------------------------------------------------------------------------*/ int ParseAuthBlock(SLPBuffer buffer, SLPAuthBlock* authblock) /* Returns - Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) or */ /* SLP_ERROR_PARSE_ERROR. */ /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ if(buffer->end - buffer->curpos < 10) { return SLP_ERROR_PARSE_ERROR; } authblock->opaque = buffer->curpos; authblock->bsd = AsUINT16(buffer->curpos); authblock->length = AsUINT16(buffer->curpos + 2); if(authblock->length > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } authblock->timestamp = AsUINT32(buffer->curpos + 4); authblock->spistrlen = AsUINT16(buffer->curpos + 8); authblock->spistr = buffer->curpos + 10; if(authblock->spistrlen > buffer->end - buffer->curpos + 10) { return SLP_ERROR_PARSE_ERROR; } authblock->authstruct = buffer->curpos + authblock->spistrlen + 10; authblock->opaquelen = authblock->length; buffer->curpos = buffer->curpos + authblock->length; return 0; } /*--------------------------------------------------------------------------*/ int ParseUrlEntry(SLPBuffer buffer, SLPUrlEntry* urlentry) /* */ /* Returns - Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) or */ /* SLP_ERROR_PARSE_ERROR. */ /*--------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 6) { return SLP_ERROR_PARSE_ERROR; } urlentry->opaque = buffer->curpos; /* parse out reserved */ urlentry->reserved = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out lifetime */ urlentry->lifetime = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; /* parse out url */ urlentry->urllen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(urlentry->urllen + 1 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } urlentry->url = buffer->curpos; buffer->curpos = buffer->curpos + urlentry->urllen; /* parse out auth block count */ urlentry->authcount = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out the auth block (if any) */ if(urlentry->authcount) { urlentry->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * urlentry->authcount); if(urlentry->autharray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(urlentry->autharray,0,sizeof(SLPAuthBlock) * urlentry->authcount); for(i=0;iauthcount;i++) { result = ParseAuthBlock(buffer,&(urlentry->autharray[i])); if(result) return result; } } urlentry->opaquelen = (char*)buffer->curpos - urlentry->opaque; return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvRqst(SLPBuffer buffer, SLPSrvRqst* srvrqst) /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ if(buffer->end - buffer->curpos < 10) { return SLP_ERROR_PARSE_ERROR; } /* parse the prlist */ srvrqst->prlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->prlistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->prlist = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->prlistlen; /* parse the service type */ srvrqst->srvtypelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->srvtypelen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->srvtype = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->srvtypelen; /* parse the scope list */ srvrqst->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->scopelistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->scopelistlen; /* parse the predicate string */ srvrqst->predicatever = 2; /* SLPv2 predicate (LDAPv3) */ srvrqst->predicatelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->predicatelen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->predicate = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->predicatelen; /* parse the slpspi string */ srvrqst->spistrlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->spistrlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->spistr = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->spistrlen; return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvRply(SLPBuffer buffer, SLPSrvRply* srvrply) /*--------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse out the error code */ srvrply->errorcode = AsUINT16(buffer->curpos); if(srvrply->errorcode) { /* We better not trust the rest of the packet */ memset( srvrply, 0, sizeof(SLPSrvRply)); srvrply->errorcode = AsUINT16(buffer->curpos); return 0; } buffer->curpos = buffer->curpos + 2; /* parse out the url entry count */ srvrply->urlcount = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; /* parse out the url entries (if any) */ if(srvrply->urlcount) { srvrply->urlarray = (SLPUrlEntry*)xmalloc(sizeof(SLPUrlEntry) * srvrply->urlcount); if(srvrply->urlarray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(srvrply->urlarray,0,sizeof(SLPUrlEntry) * srvrply->urlcount); for(i=0;iurlcount;i++) { result = ParseUrlEntry(buffer,&(srvrply->urlarray[i])); if(result) return result; } } else { srvrply->urlarray = 0; } return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvReg(SLPBuffer buffer, SLPSrvReg* srvreg) /*--------------------------------------------------------------------------*/ { int result; int i; /* Parse out the url entry */ result = ParseUrlEntry(buffer,&(srvreg->urlentry)); if(result) { return result; } if(buffer->end - buffer->curpos < 2) { return SLP_ERROR_PARSE_ERROR; } /* parse the service type */ srvreg->srvtypelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvreg->srvtypelen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvreg->srvtype = buffer->curpos; buffer->curpos = buffer->curpos + srvreg->srvtypelen; /* parse the scope list */ srvreg->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvreg->scopelistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvreg->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + srvreg->scopelistlen; /* parse the attribute list*/ srvreg->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvreg->attrlistlen + 1 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvreg->attrlist = buffer->curpos; buffer->curpos = buffer->curpos + srvreg->attrlistlen; /* parse out attribute auth block count */ srvreg->authcount = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out the auth block (if any) */ if(srvreg->authcount) { srvreg->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * srvreg->authcount); if(srvreg->autharray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(srvreg->autharray,0,sizeof(SLPAuthBlock) * srvreg->authcount); for(i=0;iauthcount;i++) { result = ParseAuthBlock(buffer,&(srvreg->autharray[i])); if(result) return result; } } return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvDeReg(SLPBuffer buffer, SLPSrvDeReg* srvdereg) /*--------------------------------------------------------------------------*/ { int result; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse the scope list */ srvdereg->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvdereg->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvdereg->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + srvdereg->scopelistlen; /* parse the url entry */ result = ParseUrlEntry(buffer,&(srvdereg->urlentry)); if(result) { return result; } /* parse the tag list */ if(buffer->end - buffer->curpos < 2) { return SLP_ERROR_PARSE_ERROR; } srvdereg->taglistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvdereg->taglistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvdereg->taglist = buffer->curpos; buffer->curpos = buffer->curpos + srvdereg->taglistlen; return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvAck(SLPBuffer buffer, SLPSrvAck* srvack) /*--------------------------------------------------------------------------*/ { srvack->errorcode = AsUINT16(buffer->curpos); return 0; } /*--------------------------------------------------------------------------*/ int ParseAttrRqst(SLPBuffer buffer, SLPAttrRqst* attrrqst) /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ if(buffer->end - buffer->curpos < 10) { return SLP_ERROR_PARSE_ERROR; } /* parse the prlist */ attrrqst->prlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->prlistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->prlist = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->prlistlen; /* parse the url */ attrrqst->urllen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->urllen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->url = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->urllen; /* parse the scope list */ attrrqst->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->scopelistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->scopelistlen; /* parse the taglist string */ attrrqst->taglistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->taglistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->taglist = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->taglistlen; /* parse the slpspi string */ attrrqst->spistrlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->spistrlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->spistr = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->spistrlen; return 0; } /*--------------------------------------------------------------------------*/ int ParseAttrRply(SLPBuffer buffer, SLPAttrRply* attrrply) /*--------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse out the error code */ attrrply->errorcode = AsUINT16(buffer->curpos); if(attrrply->errorcode) { /* We better not trust the rest of the packet */ memset(attrrply,0,sizeof(SLPAttrRply)); attrrply->errorcode = AsUINT16(buffer->curpos); return 0; } buffer->curpos = buffer->curpos + 2; /* parse out the attrlist */ attrrply->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrply->attrlistlen + 1 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrply->attrlist = buffer->curpos; buffer->curpos = buffer->curpos + attrrply->attrlistlen; /* parse out auth block count */ attrrply->authcount = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out the auth block (if any) */ if(attrrply->authcount) { attrrply->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * attrrply->authcount); if(attrrply->autharray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(attrrply->autharray,0,sizeof(SLPAuthBlock) * attrrply->authcount); for(i=0;iauthcount;i++) { result = ParseAuthBlock(buffer,&(attrrply->autharray[i])); if(result) return result; } } return 0; } /*-------------------------------------------------------------------------*/ int ParseDAAdvert(SLPBuffer buffer, SLPDAAdvert* daadvert) /*-------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse out the error code */ daadvert->errorcode = AsUINT16(buffer->curpos); if(daadvert->errorcode) { /* We better not trust the rest of the packet */ memset(daadvert,0,sizeof(SLPDAAdvert)); daadvert->errorcode = AsUINT16(buffer->curpos); return 0; } buffer->curpos = buffer->curpos + 2; /* parse out the bootstamp */ if(buffer->end - buffer->curpos < 6) { return SLP_ERROR_PARSE_ERROR; } daadvert->bootstamp = AsUINT32(buffer->curpos); buffer->curpos = buffer->curpos + 4; /* parse out the url */ daadvert->urllen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(daadvert->urllen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } daadvert->url = buffer->curpos; buffer->curpos = buffer->curpos + daadvert->urllen; /* parse the scope list */ daadvert->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(daadvert->scopelistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } daadvert->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + daadvert->scopelistlen; /* parse the attr list */ daadvert->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(daadvert->attrlistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } daadvert->attrlist = buffer->curpos; buffer->curpos = buffer->curpos + daadvert->attrlistlen; /* parse the SPI list */ daadvert->spilistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(daadvert->spilistlen + 1 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } daadvert->spilist = buffer->curpos; buffer->curpos = buffer->curpos + daadvert->spilistlen; /* parse out auth block count */ daadvert->authcount = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out the auth block (if any) */ if(daadvert->authcount) { daadvert->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * daadvert->authcount); if(daadvert->autharray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(daadvert->autharray,0,sizeof(SLPAuthBlock) * daadvert->authcount); for(i=0;iauthcount;i++) { result = ParseAuthBlock(buffer,&(daadvert->autharray[i])); if(result) return result; } } return 0; } /*-------------------------------------------------------------------------*/ int ParseSAAdvert(SLPBuffer buffer, SLPSAAdvert* saadvert) /*-------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse out the url */ saadvert->urllen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(saadvert->urllen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } saadvert->url = buffer->curpos; buffer->curpos = buffer->curpos + saadvert->urllen; /* parse the scope list */ saadvert->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(saadvert->scopelistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } saadvert->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + saadvert->scopelistlen; /* parse the attr list */ saadvert->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(saadvert->attrlistlen + 1 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } saadvert->attrlist = buffer->curpos; buffer->curpos = buffer->curpos + saadvert->attrlistlen; /* parse out auth block count */ saadvert->authcount = *(buffer->curpos); buffer->curpos = buffer->curpos + 1; /* parse out the auth block (if any) */ if(saadvert->authcount) { saadvert->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * saadvert->authcount); if(saadvert->autharray == 0) { return SLP_ERROR_INTERNAL_ERROR; } memset(saadvert->autharray,0,sizeof(SLPAuthBlock) * saadvert->authcount); for(i=0;iauthcount;i++) { result = ParseAuthBlock(buffer,&(saadvert->autharray[i])); if(result) return result; } } return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvTypeRqst(SLPBuffer buffer, SLPSrvTypeRqst* srvtyperqst) /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ if(buffer->end - buffer->curpos < 6) { return SLP_ERROR_PARSE_ERROR; } /* parse the prlist */ srvtyperqst->prlistlen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(srvtyperqst->prlistlen + 2 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvtyperqst->prlist = srvtyperqst->prlistlen ? buffer->curpos : 0; buffer->curpos += srvtyperqst->prlistlen; /* parse the naming authority if present */ srvtyperqst->namingauthlen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(!srvtyperqst->namingauthlen || srvtyperqst->namingauthlen == 0xffff) { srvtyperqst->namingauth = 0; } else { if(srvtyperqst->namingauthlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvtyperqst->namingauth = buffer->curpos; buffer->curpos += srvtyperqst->namingauthlen; } /* parse the scope list */ if(buffer->end - buffer->curpos < 2) { return SLP_ERROR_PARSE_ERROR; } srvtyperqst->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(srvtyperqst->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvtyperqst->scopelist = buffer->curpos; buffer->curpos += srvtyperqst->scopelistlen; return 0; } /*--------------------------------------------------------------------------*/ int ParseSrvTypeRply(SLPBuffer buffer, SLPSrvTypeRply* srvtyperply) /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* parse out the error code */ srvtyperply->errorcode = AsUINT16(buffer->curpos); if(srvtyperply->errorcode) { /* We better not trust the rest of the packet */ memset(srvtyperply,0,sizeof(SLPSrvTypeRply)); srvtyperply->errorcode = AsUINT16(buffer->curpos); return 0; } buffer->curpos += 2; /* parse out the error srvtype-list length */ srvtyperply->srvtypelistlen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(srvtyperply->srvtypelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvtyperply->srvtypelist = buffer->curpos; return 0; } /*--------------------------------------------------------------------------*/ int ParseExtension(SLPBuffer buffer, SLPMessage message) /* Parse extensions *after* all standard protocol fields are parsed */ /*--------------------------------------------------------------------------*/ { int extid; int nextoffset; int result = SLP_ERROR_OK; nextoffset = message->header.extoffset; while(nextoffset) { buffer->curpos = buffer->start + nextoffset; if(buffer->curpos + 5 >= buffer->end) { /* Extension takes us past the end of the buffer */ result = SLP_ERROR_PARSE_ERROR; goto CLEANUP; } extid = AsUINT16(buffer->curpos); buffer->curpos += 2; nextoffset = AsUINT24(buffer->curpos); buffer->curpos += 3; switch(extid) { case SLP_EXTENSION_ID_REG_PID: if(message->header.functionid == SLP_FUNCT_SRVREG) { /* check to see if buffer is large enough to contain the 4 byte pid */ if(buffer->curpos + 4 > buffer->end) { result = SLP_ERROR_PARSE_ERROR; goto CLEANUP; } message->body.srvreg.pid = AsUINT32(buffer->curpos); buffer->curpos += 4; } break; default: if (extid >= 0x4000 && extid <= 0x7FFF ) { /* This is a required extension. We better error out */ result = SLP_ERROR_MESSAGE_NOT_SUPPORTED; goto CLEANUP; } break; } } CLEANUP: return result; } /*=========================================================================*/ void SLPMessageFreeInternals(SLPMessage message) /*=========================================================================*/ { int i; switch(message->header.functionid) { case SLP_FUNCT_SRVRPLY: if(message->body.srvrply.urlarray) { for(i=0;ibody.srvrply.urlcount;i++) { if(message->body.srvrply.urlarray[i].autharray) { xfree(message->body.srvrply.urlarray[i].autharray); message->body.srvrply.urlarray[i].autharray = 0; } } xfree(message->body.srvrply.urlarray); message->body.srvrply.urlarray = 0; } break; case SLP_FUNCT_SRVREG: if(message->body.srvreg.urlentry.autharray) { xfree(message->body.srvreg.urlentry.autharray); message->body.srvreg.urlentry.autharray = 0; } if(message->body.srvreg.autharray) { xfree(message->body.srvreg.autharray); message->body.srvreg.autharray = 0; } break; case SLP_FUNCT_SRVDEREG: if(message->body.srvdereg.urlentry.autharray) { xfree(message->body.srvdereg.urlentry.autharray); message->body.srvdereg.urlentry.autharray = 0; } break; case SLP_FUNCT_ATTRRPLY: if(message->body.attrrply.autharray) { xfree(message->body.attrrply.autharray); message->body.attrrply.autharray = 0; } break; case SLP_FUNCT_DAADVERT: if(message->body.daadvert.autharray) { xfree(message->body.daadvert.autharray); message->body.daadvert.autharray = 0; } break; case SLP_FUNCT_SAADVERT: if(message->body.saadvert.autharray) { xfree(message->body.saadvert.autharray); message->body.saadvert.autharray = 0; } break; case SLP_FUNCT_ATTRRQST: case SLP_FUNCT_SRVACK: case SLP_FUNCT_SRVRQST: case SLP_FUNCT_SRVTYPERQST: case SLP_FUNCT_SRVTYPERPLY: default: /* don't do anything */ break; } } /*=========================================================================*/ SLPMessage SLPMessageAlloc() /* Allocates memory for a SLP message descriptor */ /* */ /* Returns - A newly allocated SLPMessage pointer of NULL on ENOMEM */ /*=========================================================================*/ { SLPMessage result = (SLPMessage)xmalloc(sizeof(struct _SLPMessage)); if(result) { memset(result,0,sizeof(struct _SLPMessage)); } return result; } /*=========================================================================*/ SLPMessage SLPMessageRealloc(SLPMessage msg) /* Reallocates memory for a SLP message descriptor */ /* */ /* Returns - A newly allocated SLPMessage pointer of NULL on ENOMEM */ /*=========================================================================*/ { if(msg == 0) { msg = SLPMessageAlloc(); if(msg == 0) { return 0; } } else { SLPMessageFreeInternals(msg); } return msg; } /*=========================================================================*/ void SLPMessageFree(SLPMessage message) /* Frees memory that might have been allocated by the SLPMessage for */ /* UrlEntryLists or AuthBlockLists. */ /* */ /* message - (IN) the SLPMessage to free */ /*=========================================================================*/ { if(message) { SLPMessageFreeInternals(message); xfree(message); } } /*=========================================================================*/ int SLPMessageParseBuffer(struct sockaddr_in* peerinfo, SLPBuffer buffer, SLPMessage message) /* Initializes a message descriptor by parsing the specified buffer. */ /* */ /* buffer - (IN) pointer the SLPBuffer to parse */ /* */ /* message - (OUT) set to describe the message from the buffer */ /* */ /* Returns - Zero on success, SLP_ERROR_PARSE_ERROR, or */ /* SLP_ERROR_INTERNAL_ERROR if out of memory. SLPMessage is */ /* invalid return is not successful. */ /* */ /* WARNING - If successful, pointers in the SLPMessage reference memory in*/ /* the parsed SLPBuffer. If SLPBufferFree() is called then the */ /* pointers in SLPMessage will be invalidated. */ /*=========================================================================*/ { int result; /* Copy in the peer info */ memcpy(&message->peer,peerinfo,sizeof(message->peer)); /* Get ready to parse */ SLPMessageFreeInternals(message); buffer->curpos = buffer->start; /* parse the header first */ result = SLPMessageParseHeader(buffer,&(message->header)); if(result == 0) { /* switch on the function id to parse the body */ switch(message->header.functionid) { case SLP_FUNCT_SRVRQST: result = ParseSrvRqst(buffer,&(message->body.srvrqst)); break; case SLP_FUNCT_SRVRPLY: result = ParseSrvRply(buffer,&(message->body.srvrply)); break; case SLP_FUNCT_SRVREG: result = ParseSrvReg(buffer,&(message->body.srvreg)); break; case SLP_FUNCT_SRVDEREG: result = ParseSrvDeReg(buffer,&(message->body.srvdereg)); break; case SLP_FUNCT_SRVACK: result = ParseSrvAck(buffer,&(message->body.srvack)); break; case SLP_FUNCT_ATTRRQST: result = ParseAttrRqst(buffer,&(message->body.attrrqst)); break; case SLP_FUNCT_ATTRRPLY: result = ParseAttrRply(buffer,&(message->body.attrrply)); break; case SLP_FUNCT_DAADVERT: result = ParseDAAdvert(buffer,&(message->body.daadvert)); break; case SLP_FUNCT_SRVTYPERQST: result = ParseSrvTypeRqst(buffer,&(message->body.srvtyperqst)); break; case SLP_FUNCT_SRVTYPERPLY: result = ParseSrvTypeRply(buffer,&(message->body.srvtyperply)); break; case SLP_FUNCT_SAADVERT: result = ParseSAAdvert(buffer,&(message->body.saadvert)); break; default: result = SLP_ERROR_MESSAGE_NOT_SUPPORTED; } } if(result == 0 && message->header.extoffset) { result = ParseExtension(buffer,message); } return result; } /*=========================================================================*/ /* Functions used to parse buffers */ /*-------------------------------------------------------------------------*/ unsigned short AsUINT16(const char *charptr) /*-------------------------------------------------------------------------*/ { unsigned char *ucp = (unsigned char *) charptr; return(ucp[0] << 8) | ucp[1]; } /*-------------------------------------------------------------------------*/ unsigned int AsUINT24(const char *charptr) /*-------------------------------------------------------------------------*/ { unsigned char *ucp = (unsigned char *) charptr; return(ucp[0] << 16) | (ucp[1] << 8) | ucp[2]; } /*-------------------------------------------------------------------------*/ unsigned int AsUINT32(const char *charptr) /*-------------------------------------------------------------------------*/ { unsigned char *ucp = (unsigned char *) charptr; return(ucp[0] << 24) | (ucp[1] << 16) | (ucp[2] << 8) | ucp[3]; } /*=========================================================================*/ /* Functions used to set buffers */ /*-------------------------------------------------------------------------*/ void ToUINT16(char *charptr, unsigned int val) /*-------------------------------------------------------------------------*/ { charptr[0] = (val >> 8) & 0xff; charptr[1] = val & 0xff; } /*-------------------------------------------------------------------------*/ void ToUINT24(char *charptr, unsigned int val) /*-------------------------------------------------------------------------*/ { charptr[0] = (val >> 16) & 0xff; charptr[1] = (val >> 8) & 0xff; charptr[2] = val & 0xff; } /*-------------------------------------------------------------------------*/ void ToUINT32(char *charptr, unsigned int val) /*-------------------------------------------------------------------------*/ { charptr[0] = (val >> 24) & 0xff; charptr[1] = (val >> 16) & 0xff; charptr[2] = (val >> 8) & 0xff; charptr[3] = val & 0xff; }