You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1213 lines
39 KiB

/***************************************************************************/
/* */
/* 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 <sys/types.h>
#include <netinet/in.h>
#endif
#if defined(ENABLE_SLPv1)
#include <slp_v1message.h>
#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;i<urlentry->authcount;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;i<srvrply->urlcount;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;i<srvreg->authcount;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;i<attrrply->authcount;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;i<daadvert->authcount;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;i<saadvert->authcount;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;i<message->body.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;
}