/** Parse a service registration. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvreg - The service registration object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvReg(SLPBuffer buffer, SLPSrvReg * srvreg) { int result; /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | <URL-Entry> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of service type string | <service-type> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <scope-list> | <scope-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of attr-list string | <attr-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |# of AttrAuths |(if present) Attribute Authentication Blocks...\ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Parse the <URL-Entry>. */ result = v2ParseUrlEntry(buffer, &srvreg->urlentry); if (result != 0) return result; /* Parse the <service-type> string. */ srvreg->srvtypelen = GetUINT16(&buffer->curpos); srvreg->srvtype = GetStrPtr(&buffer->curpos, srvreg->srvtypelen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list> string. */ srvreg->scopelistlen = GetUINT16(&buffer->curpos); srvreg->scopelist = GetStrPtr(&buffer->curpos, srvreg->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <attr-list> string. */ srvreg->attrlistlen = GetUINT16(&buffer->curpos); srvreg->attrlist = GetStrPtr(&buffer->curpos, srvreg->attrlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse AttrAuth block list (if present). */ srvreg->authcount = *buffer->curpos++; if (srvreg->authcount) { int i; srvreg->autharray = xmalloc(srvreg->authcount * sizeof(SLPAuthBlock)); if (srvreg->autharray == 0) return SLP_ERROR_INTERNAL_ERROR; memset(srvreg->autharray, 0, srvreg->authcount * sizeof(SLPAuthBlock)); for (i = 0; i < srvreg->authcount; i++) { result = v2ParseAuthBlock(buffer, &srvreg->autharray[i]); if (result != 0) return result; } } return 0; }
/** Parse an attribute reply. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] attrrply - The attribute reply object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseAttrRply(SLPBuffer buffer, SLPAttrRply * attrrply) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code | length of <attr-list> | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | <attr-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |# of AttrAuths | Attribute Authentication Block (if present) \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 attribute request size limits. */ if (buffer->end - buffer->curpos < 5) return SLP_ERROR_PARSE_ERROR; /* Parse the Error Code. */ attrrply->errorcode = GetUINT16(&buffer->curpos); if (attrrply->errorcode) { /* Don't trust the rest of the packet. */ int err = attrrply->errorcode; memset(attrrply, 0, sizeof(SLPAttrRply)); attrrply->errorcode = err; return 0; } /* Parse the <attr-list>. */ attrrply->attrlistlen = GetUINT16(&buffer->curpos); attrrply->attrlist = GetStrPtr(&buffer->curpos, attrrply->attrlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the Attribute Authentication Block list (if present). */ attrrply->authcount = *buffer->curpos++; if (attrrply->authcount) { int i; attrrply->autharray = xmalloc(attrrply->authcount * sizeof(SLPAuthBlock)); if (attrrply->autharray == 0) return SLP_ERROR_INTERNAL_ERROR; memset(attrrply->autharray, 0, attrrply->authcount * sizeof(SLPAuthBlock)); for (i = 0; i < attrrply->authcount; i++) { int result = v2ParseAuthBlock(buffer, &attrrply->autharray[i]); if (result != 0) return result; } } /* Terminate the attr list for caller convenience - overwrites the * first byte of the "# of AttrAuths" field, but we've processed it. */ if(attrrply->attrlist) ((uint8_t *)attrrply->attrlist)[attrrply->attrlistlen] = 0; return 0; }
/** Parse a URL entry. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] urlentry - The URL entry object into which * @p buffer should be parsed. * * @return Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) * or SLP_ERROR_PARSE_ERROR. * * @internal */ static int v2ParseUrlEntry(SLPBuffer buffer, SLPUrlEntry * urlentry) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reserved | Lifetime | URL Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |URL len, contd.| URL (variable length) \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |# of URL auths | Auth. blocks (if any) \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 URL entry size limits. */ if (buffer->end - buffer->curpos < 6) return SLP_ERROR_PARSE_ERROR; /* Save pointer to opaque URL entry block. */ urlentry->opaque = buffer->curpos; /* Parse individual URL entry fields. */ urlentry->reserved = *buffer->curpos++; urlentry->lifetime = GetUINT16(&buffer->curpos); urlentry->urllen = GetUINT16(&buffer->curpos); urlentry->url = GetStrPtr(&buffer->curpos, urlentry->urllen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse authentication block. */ urlentry->authcount = *buffer->curpos++; if (urlentry->authcount) { int i; urlentry->autharray = xmalloc(urlentry->authcount * sizeof(SLPAuthBlock)); if (urlentry->autharray == 0) return SLP_ERROR_INTERNAL_ERROR; memset(urlentry->autharray, 0, urlentry->authcount * sizeof(SLPAuthBlock)); for (i = 0; i < urlentry->authcount; i++) { int result = v2ParseAuthBlock(buffer, &urlentry->autharray[i]); if (result != 0) return result; } } urlentry->opaquelen = buffer->curpos - urlentry->opaque; /* Terminate the URL string for caller convenience - we're overwriting * the first byte of the "# of URL auths" field, but it's okay because * we've already read and stored it away. */ if(urlentry->url) ((uint8_t *)urlentry->url)[urlentry->urllen] = 0; return 0; }
/** Parse a service request. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvrqst - The service request object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvRqst(SLPBuffer buffer, SLPSrvRqst * srvrqst) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <PRList> | <PRList> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <service-type> | <service-type> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <scope-list> | <scope-list> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of predicate string | Service Request <predicate> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <SLP SPI> string | <SLP SPI> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce v2 service request size limits. */ if (buffer->end - buffer->curpos < 10) return SLP_ERROR_PARSE_ERROR; /* Parse the <PRList> string. */ srvrqst->prlistlen = GetUINT16(&buffer->curpos); srvrqst->prlist = GetStrPtr(&buffer->curpos, srvrqst->prlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <service-type> string. */ srvrqst->srvtypelen = GetUINT16(&buffer->curpos); srvrqst->srvtype = GetStrPtr(&buffer->curpos, srvrqst->srvtypelen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list> string. */ srvrqst->scopelistlen = GetUINT16(&buffer->curpos); srvrqst->scopelist = GetStrPtr(&buffer->curpos, srvrqst->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <predicate> string. */ srvrqst->predicatever = 2; /* SLPv2 predicate (LDAPv3) */ srvrqst->predicatelen = GetUINT16(&buffer->curpos); srvrqst->predicate = GetStrPtr(&buffer->curpos, srvrqst->predicatelen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <SLP SPI> string. */ srvrqst->spistrlen = GetUINT16(&buffer->curpos); srvrqst->spistr = GetStrPtr(&buffer->curpos, srvrqst->spistrlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
/** Parse an attribute request. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] attrrqst - The attribute request object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseAttrRqst(SLPBuffer buffer, SLPAttrRqst * attrrqst) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of PRList | <PRList> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of URL | URL \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <scope-list> | <scope-list> string \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <tag-list> string | <tag-list> string \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <SLP SPI> string | <SLP SPI> string \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce v2 attribute request size limits. */ if (buffer->end - buffer->curpos < 10) return SLP_ERROR_PARSE_ERROR; /* Parse the <PRList> string. */ attrrqst->prlistlen = GetUINT16(&buffer->curpos); attrrqst->prlist = GetStrPtr(&buffer->curpos, attrrqst->prlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the URL. */ attrrqst->urllen = GetUINT16(&buffer->curpos); attrrqst->url = GetStrPtr(&buffer->curpos, attrrqst->urllen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list> string. */ attrrqst->scopelistlen = GetUINT16(&buffer->curpos); attrrqst->scopelist = GetStrPtr(&buffer->curpos, attrrqst->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <tag-list> string. */ attrrqst->taglistlen = GetUINT16(&buffer->curpos); attrrqst->taglist = GetStrPtr(&buffer->curpos, attrrqst->taglistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <SLP SPI> string. */ attrrqst->spistrlen = GetUINT16(&buffer->curpos); attrrqst->spistr = GetStrPtr(&buffer->curpos, attrrqst->spistrlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
/** Parse an SLPv2 message header. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] header - The address of a message header into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code, either * SLP_ERROR_VER_NOT_SUPPORTED or SLP_ERROR_PARSE_ERROR. */ int SLPv2MessageParseHeader(SLPBuffer buffer, SLPHeader * header) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version | Function-ID | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length, contd.|O|F|R| reserved |Next Ext Offset| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Next Extension Offset, contd.| XID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Language Tag Length | Language Tag \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Check for invalid length - 18 bytes is the smallest v2 message. */ if (buffer->end - buffer->start < 18) return SLP_ERROR_PARSE_ERROR; /* Parse header fields. */ header->version = *buffer->curpos++; header->functionid = *buffer->curpos++; header->length = GetUINT24(&buffer->curpos); header->flags = GetUINT16(&buffer->curpos); header->encoding = 0; /* not used for SLPv2 */ header->extoffset = GetUINT24(&buffer->curpos); header->xid = GetUINT16(&buffer->curpos); header->langtaglen = GetUINT16(&buffer->curpos); header->langtag = GetStrPtr(&buffer->curpos, header->langtaglen); /* Enforce language tag size limits. */ if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Enforce function id range. */ if (header->functionid < SLP_FUNCT_SRVRQST || header->functionid > SLP_FUNCT_SAADVERT) return SLP_ERROR_PARSE_ERROR; /* Enforce reserved flags constraint. */ if (header->flags & 0x1fff) return SLP_ERROR_PARSE_ERROR; /* Enforce extension offset limits. */ if (buffer->start + header->extoffset > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
/** Parse a service extension. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] msg - The service extension object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @note Parse extensions @b after all standard protocol fields are parsed. * * @internal */ static int v2ParseExtension(SLPBuffer buffer, SLPMessage * msg) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Extension ID | Next Extension Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Offset, contd.| Extension Data \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ int result = 0; int bufsz = (int)(buffer->end - buffer->start); int nextoffset = msg->header.extoffset; while (nextoffset) { int extid; /* check for circular reference in list * if the size gets below zero, we know we're * reprocessing extensions in a loop. */ bufsz -= 5; if (bufsz <= 0) return SLP_ERROR_PARSE_ERROR; buffer->curpos = buffer->start + nextoffset; if (buffer->curpos + 5 > buffer->end) return SLP_ERROR_PARSE_ERROR; extid = GetUINT16(&buffer->curpos); nextoffset = GetUINT24(&buffer->curpos); switch (extid) { /* Support the standard and experimental versions of this extension * in order to support 1.2.x for a time while the experimental * version is deprecated. */ case SLP_EXTENSION_ID_REG_PID: case SLP_EXTENSION_ID_REG_PID_EXP: if (msg->header.functionid == SLP_FUNCT_SRVREG) { if (buffer->curpos + 4 > buffer->end) return SLP_ERROR_PARSE_ERROR; msg->body.srvreg.pid = GetUINT32(&buffer->curpos); } break; default: /* These are required extensions. Error if not handled. */ if (extid >= 0x4000 && extid <= 0x7FFF) return SLP_ERROR_OPTION_NOT_UNDERSTOOD; break; } } return result; }
/** Parse a service type reply. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvtyperply - The service type reply object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvTypeRply(SLPBuffer buffer, SLPSrvTypeRply * srvtyperply) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code | length of <srvType-list> | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | <srvtype--list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 service type reply size limits. */ if (buffer->end - buffer->curpos < 4) return SLP_ERROR_PARSE_ERROR; /* Parse the Error Code. */ srvtyperply->errorcode = GetUINT16(&buffer->curpos); if (srvtyperply->errorcode) { /* Don't trust the rest of the packet. */ int err = srvtyperply->errorcode; memset(srvtyperply, 0, sizeof(SLPSrvTypeRply)); srvtyperply->errorcode = err; return 0; } /* Parse the <srvType-list>. */ srvtyperply->srvtypelistlen = GetUINT16(&buffer->curpos); srvtyperply->srvtypelist = GetStrPtr(&buffer->curpos, srvtyperply->srvtypelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Terminate the service type list string for caller convenience - while * it appears that we're writing one byte past the end of the buffer here, * it's not so - message buffers are always allocated one byte larger than * requested for just this reason. */ if(srvtyperply->srvtypelist) ((uint8_t *)srvtyperply->srvtypelist)[srvtyperply->srvtypelistlen] = 0; return 0; }
/** Parse a service reply. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvrply - The service reply object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvRply(SLPBuffer buffer, SLPSrvRply * srvrply) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code | URL Entry count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | <URL Entry 1> ... <URL Entry N> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce v2 service reply size limits. */ if (buffer->end - buffer->curpos < 4) return SLP_ERROR_PARSE_ERROR; /* Parse out the error code. */ srvrply->errorcode = GetUINT16(&buffer->curpos); if (srvrply->errorcode) { /* don't trust the rest of the packet */ int err = srvrply->errorcode; memset(srvrply, 0, sizeof(SLPSrvRply)); srvrply->errorcode = err; return 0; } /* Parse the URL entry. */ srvrply->urlcount = GetUINT16(&buffer->curpos); if (srvrply->urlcount) { int i; srvrply->urlarray = 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++) { int result; result = v2ParseUrlEntry(buffer, &srvrply->urlarray[i]); if (result != 0) return result; } } return 0; }
/** Parse a service type request. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvtyperqst - The service type request object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvTypeRqst(SLPBuffer buffer, SLPSrvTypeRqst * srvtyperqst) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of PRList | <PRList> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of Naming Authority | <Naming Authority String> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <scope-list> | <scope-list> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 service type request size limits. */ if (buffer->end - buffer->curpos < 6) return SLP_ERROR_PARSE_ERROR; /* Parse the PRList. */ srvtyperqst->prlistlen = GetUINT16(&buffer->curpos); srvtyperqst->prlist = GetStrPtr(&buffer->curpos, srvtyperqst->prlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the Naming Authority. */ srvtyperqst->namingauthlen = GetUINT16(&buffer->curpos); if (srvtyperqst->namingauthlen == 0 || srvtyperqst->namingauthlen == 0xffff) srvtyperqst->namingauth = 0; else srvtyperqst->namingauth = GetStrPtr(&buffer->curpos, srvtyperqst->namingauthlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list>. */ srvtyperqst->scopelistlen = GetUINT16(&buffer->curpos); srvtyperqst->scopelist = GetStrPtr(&buffer->curpos, srvtyperqst->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
/** Parse an authentication block. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] authblock - The authentication block object into which * @p buffer should be parsed. * * @return Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) * or SLP_ERROR_PARSE_ERROR. * * @internal */ static int v2ParseAuthBlock(SLPBuffer buffer, SLPAuthBlock * authblock) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Structure Descriptor | Authentication Block Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SLP SPI String Length | SLP SPI String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Structured Authentication Block ... \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce v2 authentication block size limits. */ if (buffer->end - buffer->curpos < 10) return SLP_ERROR_PARSE_ERROR; /* Save pointer to opaque authentication block. */ authblock->opaque = buffer->curpos; /* Parse individual authentication block fields. */ authblock->bsd = GetUINT16(&buffer->curpos); authblock->length = GetUINT16(&buffer->curpos); authblock->timestamp = GetUINT32(&buffer->curpos); authblock->spistrlen = GetUINT16(&buffer->curpos); authblock->spistr = GetStrPtr(&buffer->curpos, authblock->spistrlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse structured authentication block. */ authblock->authstruct = (char *)buffer->curpos; authblock->opaquelen = authblock->length; buffer->curpos = authblock->opaque + authblock->length; if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
/** Parse a server ACK. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvack - The server ACK object into which * @p buffer should be parsed. * * @return Zero (success) always. * * @internal */ static int v2ParseSrvAck(SLPBuffer buffer, SLPSrvAck * srvack) { /* 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Parse the Error Code. */ srvack->errorcode = GetUINT16(&buffer->curpos); return 0; }
/** Parse a service deregistration. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] srvdereg - The service deregistration object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSrvDeReg(SLPBuffer buffer, SLPSrvDeReg * srvdereg) { int result; /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <scope-list> | <scope-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | URL Entry \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <tag-list> | <tag-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 service deregister size limits. */ if (buffer->end - buffer->curpos < 4) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list>. */ srvdereg->scopelistlen = GetUINT16(&buffer->curpos); srvdereg->scopelist = GetStrPtr(&buffer->curpos, srvdereg->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the URL entry. */ result = v2ParseUrlEntry(buffer, &srvdereg->urlentry); if (result) return result; /* Parse the <tag-list>. */ srvdereg->taglistlen = GetUINT16(&buffer->curpos); srvdereg->taglist = GetStrPtr(&buffer->curpos, srvdereg->taglistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; return 0; }
void NscScriptDecompile (CNwnStream &sStream, unsigned char *pauchData, unsigned long ulSize, NscCompiler *pCompiler) { // // Loop through the data // unsigned char *pStart = pauchData; unsigned char *pEnd = &pauchData [ulSize]; unsigned char *pData = pStart; pData += 8; while (pData < pEnd) { char szByteText [128]; char szOpText [512]; char szOpType [32]; char *pszOpRoot; // // Switch based on the next opcode // unsigned char *pOp = pData; unsigned char cOp = *pData++; switch (cOp) { case NscCode_CPDOWNSP: { if (&pData [7] > pEnd || pData [0] != 1) goto invalid_op; unsigned long ul1, ul2; pData = GetUINT32 (pData + 1, &ul1); pData = GetUINT16 (pData, &ul2); sprintf (szByteText, "%02X 01 %08X %04X", cOp, ul1, ul2); sprintf (szOpText, "CPDOWNSP %08X, %04X", ul1, ul2); } break; case NscCode_RSADD: pszOpRoot = "RSADD"; do_simple_operator:; { if (&pData [1] > pEnd) goto invalid_op; unsigned char cOpType = *pData++; GetOpText (cOpType, szOpType); sprintf (szByteText, "%02X %02X", cOp, cOpType); sprintf (szOpText, "%s%s", pszOpRoot, szOpType); } break; case NscCode_CPTOPSP: { if (&pData [7] > pEnd || pData [0] != 1) goto invalid_op; unsigned long ul1, ul2; pData = GetUINT32 (pData + 1, &ul1); pData = GetUINT16 (pData, &ul2); sprintf (szByteText, "%02X 01 %08X %04X", cOp, ul1, ul2); sprintf (szOpText, "CPTOPSP %08X, %04X", ul1, ul2); } break; case NscCode_CONST: { if (&pData [1] > pEnd) goto invalid_op; unsigned char cOpType = *pData; GetOpText (cOpType, szOpType); switch (cOpType) { case 3: case 6: { if (&pData [5] > pEnd) goto invalid_op; unsigned long ul; pData = GetUINT32 (pData + 1, &ul); sprintf (szByteText, "%02X %02X %08X", cOp, cOpType, ul); sprintf (szOpText, "CONST%s %08X", szOpType, ul); } break; case 4: { if (&pData [5] > pEnd) goto invalid_op; union { unsigned long ul; float f; } val; pData = GetFLOAT (pData + 1, &val .f); sprintf (szByteText, "%02X %02X %08X", cOp, cOpType, val .ul); sprintf (szOpText, "CONST%s %f", szOpType, val .f); } break; case 5: { if (&pData [3] > pEnd) goto invalid_op; unsigned long ul; GetUINT16 (pData + 1, &ul); if (&pData [3 + ul] > pEnd) goto invalid_op; pData += 3; char szValue [129]; unsigned long ulCopy = ul > 128 ? 128 : ul; memmove (szValue, pData, ulCopy); szValue [ulCopy] = 0; sprintf (szByteText, "%02X %02X %04X str", cOp, cOpType, ul); snprintf (szOpText, _countof (szOpText), "CONST%s \"%s\"", szOpType, szValue); pData += ul; } break; default: goto invalid_op; } } break; case NscCode_ACTION: { if (&pData [4] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1, ul2; pData = GetUINT16 (pData + 1, &ul1); ul2 = *pData++; const char *pszName = NscGetActionName ((int) ul1, pCompiler); sprintf (szByteText, "%02X 00 %04X %02X", cOp, ul1, ul2); sprintf (szOpText, "ACTION %s(%04X), %02X", pszName, ul1, ul2); } break; case NscCode_LOGAND: pszOpRoot = "LOGAND"; do_binary_operator:; { if (&pData [1] > pEnd) goto invalid_op; unsigned char cOpType = *pData++; GetOpText (cOpType, szOpType); if (cOpType == 0x24) { if (&pData [2] > pEnd) goto invalid_op; unsigned long ul1; pData = GetUINT16 (pData, &ul1); sprintf (szByteText, "%02X %02X %04X", cOp, cOpType, ul1); sprintf (szOpText, "%s%s %04X", pszOpRoot, szOpType, ul1); } else { sprintf (szByteText, "%02X %02X", cOp, cOpType); sprintf (szOpText, "%s%s", pszOpRoot, szOpType); } } break; case NscCode_LOGOR: pszOpRoot = "LOGOR"; goto do_binary_operator; case NscCode_INCOR: pszOpRoot = "INCOR"; goto do_binary_operator; case NscCode_EXCOR: pszOpRoot = "EXCOR"; goto do_binary_operator; case NscCode_BOOLAND: pszOpRoot = "BOOLAND"; goto do_binary_operator; case NscCode_EQUAL: pszOpRoot = "EQUAL"; goto do_binary_operator; case NscCode_NEQUAL: pszOpRoot = "NEQUAL"; goto do_binary_operator; case NscCode_GEQ: pszOpRoot = "GEQ"; goto do_binary_operator; case NscCode_GT: pszOpRoot = "GT"; goto do_binary_operator; case NscCode_LT: pszOpRoot = "LT"; goto do_binary_operator; case NscCode_LEQ: pszOpRoot = "LEQ"; goto do_binary_operator; case NscCode_SHLEFT: pszOpRoot = "SHLEFT"; goto do_binary_operator; case NscCode_SHRIGHT: pszOpRoot = "SHRIGHT"; goto do_binary_operator; case NscCode_USHRIGHT: pszOpRoot = "USHRIGHT"; goto do_binary_operator; case NscCode_ADD: pszOpRoot = "ADD"; goto do_binary_operator; case NscCode_SUB: pszOpRoot = "SUB"; goto do_binary_operator; case NscCode_MUL: pszOpRoot = "MUL"; goto do_binary_operator; case NscCode_DIV: pszOpRoot = "DIV"; goto do_binary_operator; case NscCode_MOD: pszOpRoot = "MOD"; goto do_binary_operator; case NscCode_NEG: pszOpRoot = "NEG"; goto do_simple_operator; case NscCode_COMP: pszOpRoot = "COMP"; goto do_simple_operator; case NscCode_MOVSP: { if (&pData [5] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 00 %08X", cOp, ul1); sprintf (szOpText, "MOVSP %08X", ul1); } break; case NscCode_STORE_STATEALL: { if (&pData [1] > pEnd) goto invalid_op; unsigned long ul = *pData++; sprintf (szByteText, "%02X %02X", cOp, ul); sprintf (szOpText, "SAVE_STATEALL %02x", ul); } break; case NscCode_JMP: { if (&pData [5] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 00 %08X", cOp, ul1); sprintf (szOpText, "JMP off_%08X", (pOp - pStart) + ul1); } break; case NscCode_JSR: { if (&pData [5] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 00 %08X", cOp, ul1); sprintf (szOpText, "JSR fn_%08X", (pOp - pStart) + ul1); } break; case NscCode_JZ: { if (&pData [5] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 00 %08X", cOp, ul1); sprintf (szOpText, "JZ off_%08X", (pOp - pStart) + ul1); } break; case NscCode_RETN: { if (&pData [1] > pEnd || pData [0] != 0) goto invalid_op; pData++; sprintf (szByteText, "%02X 00", cOp); sprintf (szOpText, "RETN"); } break; case NscCode_DESTRUCT: { if (&pData [7] > pEnd || pData [0] != 1) goto invalid_op; unsigned long ul1, ul2, ul3; pData = GetUINT16 (pData + 1, &ul1); pData = GetUINT16 (pData, &ul2); pData = GetUINT16 (pData, &ul3); sprintf (szByteText, "%02X 01 %04X %04X %04x", cOp, ul1, ul2, ul3); sprintf (szOpText, "DESTRUCT %04X, %04X, %04X", ul1, ul2, ul3); // First parameter, number of bytes to destroy // Second parameter, offset of element not to destroy // Third parameter, number of bytes no to destroy } break; case NscCode_NOT: pszOpRoot = "NOT"; goto do_simple_operator; case NscCode_DECISP: { if (&pData [5] > pEnd || pData [0] != 3) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 03 %08X", cOp, ul1); sprintf (szOpText, "DECISP %08X", ul1); } break; case NscCode_INCISP: { if (&pData [5] > pEnd || pData [0] != 3) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 03 %08X", cOp, ul1); sprintf (szOpText, "INCISP %08X", ul1); } break; case NscCode_JNZ: { if (&pData [5] > pEnd || pData [0] != 0) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 00 %08X", cOp, ul1); sprintf (szOpText, "JNZ off_%08X", (pOp - pStart) + ul1); } break; case NscCode_CPDOWNBP: { if (&pData [7] > pEnd || pData [0] != 1) goto invalid_op; unsigned long ul1, ul2; pData = GetUINT32 (pData + 1, &ul1); pData = GetUINT16 (pData, &ul2); sprintf (szByteText, "%02X 01 %08X %04X", cOp, ul1, ul2); sprintf (szOpText, "CPDOWNBP %08X, %04X", ul1, ul2); } break; case NscCode_CPTOPBP: { if (&pData [7] > pEnd || pData [0] != 1) goto invalid_op; unsigned long ul1, ul2; pData = GetUINT32 (pData + 1, &ul1); pData = GetUINT16 (pData, &ul2); sprintf (szByteText, "%02X 01 %08X %04X", cOp, ul1, ul2); sprintf (szOpText, "CPTOPBP %08X, %04X", ul1, ul2); } break; case NscCode_DECIBP: { if (&pData [5] > pEnd || pData [0] != 3) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 03 %08X", cOp, ul1); sprintf (szOpText, "DECIBP %08X", ul1); } break; case NscCode_INCIBP: { if (&pData [5] > pEnd || pData [0] != 3) goto invalid_op; unsigned long ul1; pData = GetUINT32 (pData + 1, &ul1); sprintf (szByteText, "%02X 03 %08X", cOp, ul1); sprintf (szOpText, "INCIBP %08X", ul1); } break; case NscCode_SAVEBP: { if (&pData [1] > pEnd || pData [0] != 0) goto invalid_op; pData++; sprintf (szByteText, "%02X 00", cOp); sprintf (szOpText, "SAVEBP"); } break; case NscCode_RESTOREBP: { if (&pData [1] > pEnd || pData [0] != 0) goto invalid_op; pData++; sprintf (szByteText, "%02X 00", cOp); sprintf (szOpText, "RESTOREBP"); } break; case NscCode_STORE_STATE: { if (&pData [9] > pEnd) goto invalid_op; unsigned long ul1, ul2, ul3; ul3 = *pData++; pData = GetUINT32 (pData, &ul1); pData = GetUINT32 (pData, &ul2); sprintf (szByteText, "%02X %02X %08X %08X", cOp, ul3, ul1, ul2); sprintf (szOpText, "STORE_STATE %02X, %08X, %08X", ul3, ul1, ul2); // First value is BP stack size to save // second value is SP stack size to save } break; case NscCode_NOP: { if (&pData [1] > pEnd || pData [0] != 0) goto invalid_op; pData++; sprintf (szByteText, "%02X 00", cOp); sprintf (szOpText, "NOP"); } break; case NscCode_Size: { if (&pData [4] > pEnd) goto invalid_op; unsigned long ul; pData = GetUINT32 (pData, &ul); sprintf (szByteText, "%02X %08X", cOp, ul); sprintf (szOpText, "T %08X", ul); } break; default: invalid_op:; sprintf (szByteText, "%02X", cOp); sprintf (szOpText, "??"); //if (g_fpDebug) // fprintf (g_fpDebug, "Unknown opcode %02x\r\n", cOp); break; } // // Format the final line // char szText [1024]; sprintf (szText, "%08X %-24s %s", pOp - pStart, szByteText, szOpText); sStream .WriteLine (szText); } }
/** Parse an SA advertisement. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] saadvert - The SA advertisement object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseSAAdvert(SLPBuffer buffer, SLPSAAdvert * saadvert) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of URL | URL \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <scope-list> | <scope-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <attr-list> | <attr-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | # auth blocks | authentication block (if any) \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 SA advertisement size limits. */ if (buffer->end - buffer->curpos < 7) return SLP_ERROR_PARSE_ERROR; /* Parse out the URL. */ saadvert->urllen = GetUINT16(&buffer->curpos); saadvert->url = GetStrPtr(&buffer->curpos, saadvert->urllen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list>. */ saadvert->scopelistlen = GetUINT16(&buffer->curpos); saadvert->scopelist = GetStrPtr(&buffer->curpos, saadvert->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <attr-list>. */ saadvert->attrlistlen = GetUINT16(&buffer->curpos); saadvert->attrlist = GetStrPtr(&buffer->curpos, saadvert->attrlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the authentication block list (if any). */ saadvert->authcount = *buffer->curpos++; if (saadvert->authcount) { int i; saadvert->autharray = xmalloc(saadvert->authcount * sizeof(SLPAuthBlock)); if (saadvert->autharray == 0) return SLP_ERROR_INTERNAL_ERROR; memset(saadvert->autharray, 0, saadvert->authcount * sizeof(SLPAuthBlock)); for (i = 0; i < saadvert->authcount; i++) { int result = v2ParseAuthBlock(buffer, &saadvert->autharray[i]); if (result != 0) return result; } } /* Terminate the URL string for caller convenience - we're overwriting * the first byte of the "Length of <scope-list>" field, but it's okay * because we've already read and stored it away. */ if(saadvert->url) ((uint8_t *)saadvert->url)[saadvert->urllen] = 0; return 0; }
/** Parse a DA advertisement. * * @param[in] buffer - The buffer from which data should be parsed. * @param[out] daadvert - The DA advertisement object into which * @p buffer should be parsed. * * @return Zero on success, or a non-zero error code. * * @internal */ static int v2ParseDAAdvert(SLPBuffer buffer, SLPDAAdvert * daadvert) { /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code | DA Stateless Boot Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DA Stateless Boot Time,, contd.| Length of URL | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \ URL \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <scope-list> | <scope-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <attr-list> | <attr-list> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length of <SLP SPI List> | <SLP SPI List> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | # Auth Blocks | Authentication block (if any) \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Enforce SLPv2 DA advertisement size limits. */ if (buffer->end - buffer->curpos < 15) return SLP_ERROR_PARSE_ERROR; /* Parse the Error Code. */ daadvert->errorcode = GetUINT16(&buffer->curpos); if (daadvert->errorcode) { /* Don't trust the rest of the packet. */ int err = daadvert->errorcode; memset(daadvert, 0, sizeof(SLPDAAdvert)); daadvert->errorcode = err; return 0; } /* Parse the DA Stateless Boot Timestamp. */ daadvert->bootstamp = GetUINT32(&buffer->curpos); /* Parse out the URL. */ daadvert->urllen = GetUINT16(&buffer->curpos); daadvert->url = GetStrPtr(&buffer->curpos, daadvert->urllen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <scope-list>. */ daadvert->scopelistlen = GetUINT16(&buffer->curpos); daadvert->scopelist = GetStrPtr(&buffer->curpos, daadvert->scopelistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <attr-list>. */ daadvert->attrlistlen = GetUINT16(&buffer->curpos); daadvert->attrlist = GetStrPtr(&buffer->curpos, daadvert->attrlistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the <SLP SPI List> String. */ daadvert->spilistlen = GetUINT16(&buffer->curpos); daadvert->spilist = GetStrPtr(&buffer->curpos, daadvert->spilistlen); if (buffer->curpos > buffer->end) return SLP_ERROR_PARSE_ERROR; /* Parse the authentication block list (if any). */ daadvert->authcount = *buffer->curpos++; if (daadvert->authcount) { int i; daadvert->autharray = 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++) { int result = v2ParseAuthBlock(buffer, &daadvert->autharray[i]); if (result != 0) return result; } } /* Terminate the URL string for caller convenience - we're overwriting * the first byte of the "Length of <scope-list>" field, but it's okay * because we've already read and stored it away. */ if(daadvert->url) ((uint8_t *)daadvert->url)[daadvert->urllen] = 0; return 0; }