/*--------------------------------------------------------------------------*/ 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->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; buffer->curpos = buffer->curpos + authblock->length; 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); 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 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; } /* 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 > 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*)malloc(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; } } return 0; }
/*--------------------------------------------------------------------------*/ int ParseAttrRply(SLPBuffer buffer, SLPAttrRply* attrrply) /*--------------------------------------------------------------------------*/ { int result; int i; /* make sure that min size is met */ #if(defined(PARANOID) || defined(DEBUG)) if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } #endif /* parse out the error code */ attrrply->errorcode = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; /* parse out the attrlist */ attrrply->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; #if(defined(PARANOID) || defined(DEBUG)) if(attrrply->attrlistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif 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*)malloc(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 SLPv1MessageParseHeader(SLPBuffer buffer, SLPHeader* header) /* */ /* Returns - Zero on success, SLP_ERROR_VER_NOT_SUPPORTED, or */ /* SLP_ERROR_PARSE_ERROR. */ /*=========================================================================*/ { header->version = *(buffer->curpos); header->functionid = *(buffer->curpos + 1); header->length = AsUINT16(buffer->curpos + 2); header->flags = *(buffer->curpos + 4); header->encoding = AsUINT16(buffer->curpos + 8); header->extoffset = 0; /* not used for SLPv1 */ header->xid = AsUINT16(buffer->curpos + 10); header->langtaglen = 2; header->langtag = buffer->curpos + 6; if(header->functionid > SLP_FUNCT_SRVTYPERQST) { /* invalid function id */ return SLP_ERROR_PARSE_ERROR; } if(header->encoding != SLP_CHAR_ASCII && header->encoding != SLP_CHAR_UTF8 && header->encoding != SLP_CHAR_UNICODE16 && header->encoding != SLP_CHAR_UNICODE32) { return SLP_ERROR_CHARSET_NOT_UNDERSTOOD; } if(header->length != buffer->end - buffer->start || header->length < 12) { /* invalid length 12 bytes is the smallest v1 message*/ return SLP_ERROR_PARSE_ERROR; } /* TODO - do something about the other flags */ if(header->flags & 0x07) { /* invalid flags */ return SLP_ERROR_PARSE_ERROR; } buffer->curpos += 12; return 0; }
/*--------------------------------------------------------------------------*/ int v1ParseSrvDeReg(SLPBuffer buffer, SLPHeader* header, SLPSrvDeReg* srvdereg) /*--------------------------------------------------------------------------*/ { int result; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } /* SLPv1 deregistrations do not have a separate scope list */ srvdereg->scopelistlen = 0; srvdereg->scopelist = 0; /* parse the url */ srvdereg->urlentry.reserved = 0; /* not present in SLPv1 */ srvdereg->urlentry.lifetime = 0; /* not present in SLPv1 */ srvdereg->urlentry.urllen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(srvdereg->urlentry.urllen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvdereg->urlentry.url = buffer->curpos; buffer->curpos += srvdereg->urlentry.urllen; result = SLPv1AsUTF8(header->encoding, (char *) srvdereg->urlentry.url, &srvdereg->urlentry.urllen); if(result) { return result; } /* parse the tag list */ 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; result = SLPv1AsUTF8(header->encoding, (char *) srvdereg->taglist, &srvdereg->taglistlen); 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 > 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 */ 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 ParseSrvDeReg(SLPBuffer buffer, SLPSrvDeReg* srvdereg) /*--------------------------------------------------------------------------*/ { int result; /* make sure that min size is met */ #if(defined(PARANOID) || defined(DEBUG)) if(buffer->end - buffer->curpos < 4) { return SLP_ERROR_PARSE_ERROR; } #endif /* parse the scope list */ srvdereg->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; #if(defined(PARANOID) || defined(DEBUG)) if(srvdereg->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif 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 */ srvdereg->taglistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; #if(defined(PARANOID) || defined(DEBUG)) if(srvdereg->taglistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif srvdereg->taglist = buffer->curpos; buffer->curpos = buffer->curpos + srvdereg->taglistlen; return 0; }
/*--------------------------------------------------------------------------*/ int v1ParseUrlEntry(SLPBuffer buffer, SLPHeader* header, SLPUrlEntry* urlentry) /* */ /* Returns - Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) or */ /* SLP_ERROR_PARSE_ERROR. */ /*--------------------------------------------------------------------------*/ { int result; /* make sure that min size is met */ if(buffer->end - buffer->curpos < 6) { return SLP_ERROR_PARSE_ERROR; } /* no reserved stuff for SLPv1 */ urlentry->reserved = 0; /* 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 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } urlentry->url = buffer->curpos; buffer->curpos = buffer->curpos + urlentry->urllen; result = SLPv1AsUTF8(header->encoding, (char *) urlentry->url, &urlentry->urllen); if(result) { return result; } /* we don't support auth blocks for SLPv1 - no one uses them anyway */ urlentry->authcount = 0; urlentry->autharray = 0; 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); 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*)malloc(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 ParseHeader(SLPBuffer buffer, SLPHeader* header) /* */ /* Returns - Zero on success, SLP_ERROR_VER_NOT_SUPPORTED, or */ /* SLP_ERROR_PARSE_ERROR. */ /*-------------------------------------------------------------------------*/ { header->version = *(buffer->curpos); header->functionid = *(buffer->curpos + 1); header->length = AsUINT24(buffer->curpos + 2); header->flags = AsUINT16(buffer->curpos + 5); header->extoffset = AsUINT24(buffer->curpos + 7); header->xid = AsUINT16(buffer->curpos + 10); header->langtaglen = AsUINT16(buffer->curpos + 12); header->langtag = buffer->curpos + 14; if(header->version != 2) { return SLP_ERROR_VER_NOT_SUPPORTED; } if(header->functionid > SLP_FUNCT_SAADVERT) { /* invalid function id */ return SLP_ERROR_PARSE_ERROR; } if(header->length != buffer->end - buffer->start || header->length < 18) { /* invalid length 18 bytes is the smallest v2 message*/ return SLP_ERROR_PARSE_ERROR; } if(header->flags & 0x1fff) { /* invalid flags */ return SLP_ERROR_PARSE_ERROR; } buffer->curpos = buffer->curpos + header->langtaglen + 14; 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 > 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 > 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 > 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 > 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 ParseSrvAck(SLPBuffer buffer, SLPSrvAck* srvack) /*--------------------------------------------------------------------------*/ { srvack->errorcode = AsUINT16(buffer->curpos); 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; } /* parse the service type */ srvreg->srvtypelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvreg->srvtypelen > 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 > 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 > 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*)malloc(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 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 > 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 > 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 > 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 > 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 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); buffer->curpos = buffer->curpos + 2; /* parse out the bootstamp */ 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 > 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 > 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 > 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 > 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*)malloc(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 v1ParseSrvTypeRqst(SLPBuffer buffer, SLPHeader* header, SLPSrvTypeRqst* srvtyperqst) /*--------------------------------------------------------------------------*/ { int result; /* 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 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvtyperqst->prlist = srvtyperqst->prlistlen ? buffer->curpos : 0; buffer->curpos += srvtyperqst->prlistlen; result = SLPv1AsUTF8(header->encoding, (char *) srvtyperqst->prlist, &srvtyperqst->prlistlen); if(result) return result; /* 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; result = SLPv1AsUTF8(header->encoding, (char *) srvtyperqst->namingauth, &srvtyperqst->namingauthlen); if(result) return result; } /* parse the scope list */ srvtyperqst->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos += 2; if(srvtyperqst->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } if(srvtyperqst->scopelistlen) { srvtyperqst->scopelist = buffer->curpos; buffer->curpos += srvtyperqst->scopelistlen; result = SLPv1AsUTF8(header->encoding, (char *) srvtyperqst->scopelist, &srvtyperqst->scopelistlen); if(result) return result; } else { srvtyperqst->scopelist = "default"; srvtyperqst->scopelistlen = 7; } return 0; }
/*--------------------------------------------------------------------------*/ int v1ParseAttrRqst(SLPBuffer buffer, SLPHeader* header, SLPAttrRqst* attrrqst) /*--------------------------------------------------------------------------*/ { int result; /* 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 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->prlist = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->prlistlen; result = SLPv1AsUTF8(header->encoding, (char *) attrrqst->prlist, &attrrqst->prlistlen); if(result) return result; /* parse the url */ attrrqst->urllen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->urllen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->url = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->urllen; result = SLPv1AsUTF8(header->encoding, (char *) attrrqst->url, &attrrqst->urllen); if(result) return result; /* parse the scope list */ attrrqst->scopelistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } if(attrrqst->scopelistlen) { attrrqst->scopelist = buffer->curpos; buffer->curpos += attrrqst->scopelistlen; result = SLPv1AsUTF8(header->encoding, (char *) attrrqst->scopelist, &attrrqst->scopelistlen); if(result) return result; } else { attrrqst->scopelist = "default"; attrrqst->scopelistlen = 7; } /* parse the taglist string */ attrrqst->taglistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(attrrqst->taglistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } attrrqst->taglist = buffer->curpos; buffer->curpos = buffer->curpos + attrrqst->taglistlen; result = SLPv1AsUTF8(header->encoding, (char *) attrrqst->taglist, &attrrqst->taglistlen); if(result) return result; /* SLPv1 service requests don't have SPI strings */ attrrqst->spistrlen = 0; attrrqst->spistr = 0; return 0; }
/*--------------------------------------------------------------------------*/ int v1ParseSrvReg(SLPBuffer buffer, SLPHeader* header, SLPSrvReg* srvreg) /*--------------------------------------------------------------------------*/ { char *tmp; int result; /* Parse out the url entry */ result = v1ParseUrlEntry(buffer, header, &(srvreg->urlentry)); if(result) { return result; } /* SLPv1 registration requests don't have a separate service type. They must be parsed from the url */ srvreg->srvtype = srvreg->urlentry.url; tmp = strstr(srvreg->srvtype, ":/"); if(!tmp) return SLP_ERROR_PARSE_ERROR; srvreg->srvtypelen = tmp - srvreg->srvtype; /* parse the attribute list */ srvreg->attrlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvreg->attrlistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvreg->attrlist = buffer->curpos; buffer->curpos = buffer->curpos + srvreg->attrlistlen; result = SLPv1AsUTF8(header->encoding, (char *) srvreg->attrlist, &srvreg->attrlistlen); if(result) { return result; } /* SLPv1 registration requests don't include a scope either. The scope is included in the attribute list */ if((tmp = strstr(srvreg->attrlist, "SCOPE")) || (tmp = strstr(srvreg->attrlist, "scope"))) { tmp += 5; /* go past the scope */ while(*tmp && (isspace((unsigned char)*tmp) || *tmp == '=')) tmp++; /* go past = and white space */ srvreg->scopelist = tmp; while(*tmp && !isspace((unsigned char)*tmp) && *tmp != ')') tmp++; /* find end of scope */ srvreg->scopelistlen = tmp - srvreg->scopelist; } else { srvreg->scopelist = "default"; srvreg->scopelistlen = 7; } /* we don't support auth blocks for SLPv1 - no one uses them anyway */ srvreg->authcount = 0; srvreg->autharray = 0; return 0; }
/*--------------------------------------------------------------------------*/ int v1ParseSrvRqst(SLPBuffer buffer, SLPHeader* header, SLPSrvRqst* srvrqst) /*--------------------------------------------------------------------------*/ { char *tmp; int result; /* 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 > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->prlist = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->prlistlen; result = SLPv1AsUTF8(header->encoding, (char *) srvrqst->prlist, &srvrqst->prlistlen); if(result) return result; /* parse the predicate string */ srvrqst->predicatelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; if(srvrqst->predicatelen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } srvrqst->predicate = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->predicatelen; result = SLPv1AsUTF8(header->encoding, (char *) srvrqst->predicate, &srvrqst->predicatelen); if(result) { return result; } /* null terminate the predicate */ * (char *) (srvrqst->predicate + srvrqst->predicatelen) = '\0'; /* Now split out the service type */ srvrqst->srvtype = srvrqst->predicate; tmp = strchr(srvrqst->srvtype, '/'); if(!tmp) return SLP_ERROR_PARSE_ERROR; *tmp = 0; /* null terminate service type */ srvrqst->srvtypelen = tmp - srvrqst->srvtype; /* Parse out the predicate */ srvrqst->predicatever = 1; /* SLPv1 predicate (a bit messy) */ srvrqst->predicatelen -= srvrqst->srvtypelen + 1; srvrqst->predicate += srvrqst->srvtypelen + 1; /* Now split out the scope (if any) */ if(*srvrqst->predicate == '/') { /* no scope - so set default scope */ srvrqst->scopelist = "default"; srvrqst->scopelistlen = 7; srvrqst->predicate++; srvrqst->predicatelen--; } else { srvrqst->scopelist = srvrqst->predicate; tmp = strchr(srvrqst->scopelist, '/'); if(!tmp) return SLP_ERROR_PARSE_ERROR; /* null terminate scope list */ *tmp = 0; srvrqst->scopelistlen = tmp - srvrqst->scopelist; srvrqst->predicate += srvrqst->scopelistlen + 1; srvrqst->predicatelen -= srvrqst->scopelistlen + 1; } srvrqst->predicatelen--; tmp = (char*)(srvrqst->predicate + srvrqst->predicatelen); /* null term. pred */ *tmp = 0; /* SLPv1 service requests don't have SPI strings */ srvrqst->spistrlen = 0; srvrqst->spistr = 0; return 0; }
/*-------------------------------------------------------------------------*/ int ParseHeader(SLPBuffer buffer, SLPHeader* header) /* */ /* Returns - Zero on success, SLP_ERROR_VER_NOT_SUPPORTED, or */ /* SLP_ERROR_PARSE_ERROR. */ /*-------------------------------------------------------------------------*/ { header->version = *(buffer->curpos); header->functionid = *(buffer->curpos + 1); #if defined(ENABLE_SLPv1) if(header->version == 1) { return v1ParseHeader(buffer, header); } #endif if(header->version != 2) { return SLP_ERROR_VER_NOT_SUPPORTED; } 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; } /* check for invalid length 18 bytes is the smallest v2 message*/ if(header->length != buffer->end - buffer->start || header->length < 18) { 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; }
/*-------------------------------------------------------------------------*/ void IncomingStreamRead(SLPList* socklist, SLPDSocket* sock) /*-------------------------------------------------------------------------*/ { int bytesread, recvlen = 0; char peek[16]; int peeraddrlen = sizeof(struct sockaddr_in); if (sock->state == STREAM_READ_FIRST) { /*---------------------------------------------------*/ /* take a peek at the packet to get size information */ /*---------------------------------------------------*/ bytesread = recvfrom(sock->fd, peek, 16, MSG_PEEK, (struct sockaddr *)&(sock->peeraddr), &peeraddrlen); if (bytesread > 0) { if (*peek == 2) recvlen = AsUINT24(peek + 2); else if (*peek == 1) /* SLPv1 packet */ recvlen = AsUINT16(peek + 2); /* allocate the recvbuf big enough for the whole message */ sock->recvbuf = SLPBufferRealloc(sock->recvbuf,recvlen); if (sock->recvbuf) { sock->state = STREAM_READ; } else { SLPDLog("INTERNAL_ERROR - out of memory!\n"); sock->state = SOCKET_CLOSE; } } else { sock->state = SOCKET_CLOSE; return; } } if (sock->state == STREAM_READ) { /*------------------------------*/ /* recv the rest of the message */ /*------------------------------*/ bytesread = recv(sock->fd, sock->recvbuf->curpos, sock->recvbuf->end - sock->recvbuf->curpos, 0); if (bytesread > 0) { /* reset age to max because of activity */ sock->age = 0; sock->recvbuf->curpos += bytesread; if (sock->recvbuf->curpos == sock->recvbuf->end) { switch (SLPDProcessMessage(&sock->peeraddr, sock->recvbuf, &(sock->sendbuf))) { case SLP_ERROR_PARSE_ERROR: case SLP_ERROR_VER_NOT_SUPPORTED: case SLP_ERROR_MESSAGE_NOT_SUPPORTED: sock->state = SOCKET_CLOSE; break; default: sock->state = STREAM_WRITE_FIRST; IncomingStreamWrite(socklist, sock); } } } else { /* error in recv() */ sock->state = SOCKET_CLOSE; } } }
/*-------------------------------------------------------------------------*/ int DHCPParseSLPTags(int tag, void *optdata, size_t optdatasz, void *context) /* Callback routined tests each DA discovered from DHCP and add it to the */ /* DA cache. */ /* */ /* Returns: 0 on success, or nonzero to stop being called. */ /*-------------------------------------------------------------------------*/ { int cpysz, bufsz; DHCPContext *ctxp = (DHCPContext *)context; unsigned char *p = (unsigned char *)optdata; unsigned char flags, dasize; int encoding; /* filter out zero length options */ if (!optdatasz) return 0; switch(tag) { case TAG_SLP_SCOPE: /* Draft 3 format is only supported for ASCII and UNICODE character encodings - UTF8 encodings must use rfc2610 format. To determine the format, we parse 2 bytes and see if the result is a valid encoding. If so it's draft 3, otherwise rfc2610. */ encoding = (optdatasz > 1)? AsUINT16(p): 0; if (encoding != CT_ASCII && encoding != CT_UNICODE) { /* rfc2610 format */ if (optdatasz == 1) break; /* UA's should ignore statically configured scopes for this interface - add code to handle this later... */ flags = *p++; /* pick up the mandatory flag... */ optdatasz--; if (flags) ; /* ...and add code to handle it later... */ /* copy utf8 string into return buffer */ cpysz = optdatasz < sizeof(ctxp->scopelist)? optdatasz: sizeof(ctxp->scopelist); strncpy(ctxp->scopelist, (char*)p, cpysz); ctxp->scopelist[sizeof(ctxp->scopelist) - 1] = 0; } else { /* draft 3 format: defined to configure scopes for SA's only so we should flag the scopes to be used only as registration filter scopes - add code to handle this case later... offs len name description 0 2 encoding character encoding used 2 n scopelist list of scopes as asciiz string. */ optdatasz -= 2; /* skip encoding bytes */ p += 2; /* if UNICODE encoding is used convert to utf8 */ if (encoding == CT_UNICODE) wcstombs(ctxp->scopelist, (wchar_t*)p, sizeof(ctxp->scopelist)); else { cpysz = optdatasz < sizeof(ctxp->scopelist)? optdatasz: sizeof(ctxp->scopelist); strncpy(ctxp->scopelist, (char*)p, cpysz); ctxp->scopelist[sizeof(ctxp->scopelist) - 1] = 0; } } break; case TAG_SLP_DA: flags = *p++; optdatasz--; /* If the flags byte has the high bit set, we know we are using draft 3 format, otherwise rfc2610 format. */ if (!(flags & DA_NAME_PRESENT)) { /* rfc2610 format */ if (flags) { /* If the mandatory byte is non-zero, indicate that multicast is not to be used to dynamically discover directory agents on this interface by setting the LACBF_STATIC_DA flag in the LACB for this interface. */ /* skip this for now - deal with it later... */ } bufsz = sizeof(ctxp->addrlist) - ctxp->addrlistlen; cpysz = (int)optdatasz < bufsz? optdatasz: bufsz; memcpy(ctxp->addrlist + ctxp->addrlistlen, p, cpysz); ctxp->addrlistlen += cpysz; } else { /* pre-rfc2610 (draft 3) format: offs len name description 0 1 flags contains 4 flags (defined above) 1 1 dasize name or addr length 2 dasize daname da name or ip address (flags) */ dasize = *p++; optdatasz--; if (dasize > optdatasz) dasize = optdatasz; if (flags & DA_NAME_IS_DNS) ; /* DA name contains dns name - we have to resolve - later... */ else { /* DA name is one 4-byte ip address */ if (dasize < 4) break; /* oops, bad option format */ dasize = 4; bufsz = sizeof(ctxp->addrlist) - ctxp->addrlistlen; cpysz = dasize < bufsz? dasize: bufsz; memcpy(ctxp->addrlist + ctxp->addrlistlen, p, cpysz); ctxp->addrlistlen += cpysz; } if (flags & DISABLE_DA_MCAST) ; /* this is the equivalent of the rfc2610 mandatory bit */ } break; } return 0; }
/*--------------------------------------------------------------------------*/ int ParseSrvRqst(SLPBuffer buffer, SLPSrvRqst* srvrqst) /*--------------------------------------------------------------------------*/ { /* make sure that min size is met */ #if(defined(PARANOID) || defined(DEBUG)) if(buffer->end - buffer->curpos < 10) { return SLP_ERROR_PARSE_ERROR; } #endif /* parse the prlist */ srvrqst->prlistlen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; #if(defined(PARANOID) || defined(DEBUG)) if(srvrqst->prlistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif 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(defined(PARANOID) || defined(DEBUG)) if(srvrqst->srvtypelen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif 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(defined(PARANOID) || defined(DEBUG)) if(srvrqst->scopelistlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif srvrqst->scopelist = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->scopelistlen; /* parse the predicate string */ srvrqst->predicatelen = AsUINT16(buffer->curpos); buffer->curpos = buffer->curpos + 2; #if(defined(PARANOID) || defined(DEBUG)) if(srvrqst->predicatelen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif 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(defined(PARANOID) || defined(DEBUG)) if(srvrqst->spistrlen > buffer->end - buffer->curpos) { return SLP_ERROR_PARSE_ERROR; } #endif srvrqst->spistr = buffer->curpos; buffer->curpos = buffer->curpos + srvrqst->spistrlen; return 0; }