/** Process a SrvTypeRequest message. * * @param[in] message - The message to process. * @param[out] sendbuf - The response buffer to fill. * @param[in] errorcode - The error code from the client request. * * @return Zero on success, or a non-zero SLP error on failure. * * @internal */ static int ProcessSrvTypeRqst(SLPMessage * message, SLPBuffer * sendbuf, int errorcode) { size_t size = 0; SLPDDatabaseSrvTypeRqstResult * db = 0; SLPBuffer result = *sendbuf; /* If errorcode is set, we can not be sure that message is good Go directly to send response code */ if (errorcode) goto RESPOND; /* check for one of our IP addresses in the prlist */ if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen, message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { /* Silently ignore */ result->end = result->start; goto FINISHED; } /* make sure that we handle the scope */ if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen, message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db); else errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; RESPOND: /* do not send error codes or empty replies to multicast requests */ if (errorcode != 0 || db->srvtypelistlen == 0) if (message->header.flags & SLP_FLAG_MCAST || SLPNetIsMCast(&(message->peer))) { result->end = result->start; goto FINISHED; } /* ensure the buffer is big enough to handle the whole srvtyperply */ size = message->header.langtaglen + 18; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for srvtype len */ if (errorcode == 0) size += db->srvtypelistlen; /* Reallocate the result buffer */ result = SLPBufferRealloc(result, size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /* Add the header */ /* version */ *result->curpos++ = 2; /* function id */ *result->curpos++ = SLP_FUNCT_SRVTYPERPLY; /* length */ PutUINT24(&result->curpos, size); /* flags */ PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? SLP_FLAG_OVERFLOW: 0)); /* ext offset */ PutUINT24(&result->curpos, 0); /* xid */ PutUINT16(&result->curpos, message->header.xid); /* lang tag len */ PutUINT16(&result->curpos, message->header.langtaglen); /* lang tag */ memcpy(result->curpos, message->header.langtag, message->header.langtaglen); result->curpos += message->header.langtaglen; /* Add rest of the SrvTypeRply */ /* error code*/ PutUINT16(&result->curpos, errorcode); if (errorcode == 0) { /* length of srvtype-list */ PutUINT16(&result->curpos, db->srvtypelistlen); memcpy(result->curpos, db->srvtypelist, db->srvtypelistlen); result->curpos += db->srvtypelistlen; } FINISHED: if (db) SLPDDatabaseSrvTypeRqstEnd(db); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvTypeRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { char* type; char* end; char* slider; int i; int typelen; int numsrvtypes = 0; int size = 0; SLPDDatabaseSrvTypeRqstResult* db = 0; SLPBuffer result = *sendbuf; /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen, message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------------------------------------*/ if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen, message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes) != 0) { /*------------------------------------*/ /* Find service types in the database */ /*------------------------------------*/ errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { if (errorcode != 0 || db->srvtypelistlen == 0) { result->end = result->start; goto FINISHED; } } /*-----------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvtyperply */ /*-----------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for num of service types */ if (errorcode == 0) { if (db->srvtypelistlen) { /* there has to be at least one service type*/ numsrvtypes = 1; /* count the rest of the service types */ type = db->srvtypelist; for (i=0; i< db->srvtypelistlen; i++) { if (type[i] == ',') { numsrvtypes += 1; } } /* figure out how much memory is required for srvtype strings */ typelen = INT_MAX; errorcode = SLPv1ToEncoding(0, &typelen, message->header.encoding, db->srvtypelist, db->srvtypelistlen); /* TRICKY: we add in the numofsrvtypes + 1 to make room for the */ /* type length. We can do this because the ',' of the comma */ /* delimited list is one byte. */ size = size + typelen + numsrvtypes + 1; } else { numsrvtypes = 0; } } /*-----------------*/ /* Allocate memory */ /*-----------------*/ result = SLPBufferRealloc(result,size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVTYPERPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-----------------------------*/ /* Add rest of the SrvTypeRply */ /*-----------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos += 2; if (errorcode == 0) { /* num of service types */ ToUINT16(result->curpos, numsrvtypes); result->curpos += 2; /* service type strings */ type = db->srvtypelist; slider = db->srvtypelist; end = &(type[db->srvtypelistlen]); for (i=0;i<numsrvtypes; i++) { while (slider < end && *slider != ',') slider++; typelen = size; /* put in the encoded service type */ SLPv1ToEncoding(result->curpos + 2, &typelen, message->header.encoding, type, slider - type); /* slip in the typelen */ ToUINT16(result->curpos, typelen); result->curpos += 2; result->curpos += typelen; slider ++; /* skip comma */ type = slider; } /* TODO - make sure we don't return generic types */ } FINISHED: if (db) SLPDDatabaseSrvTypeRqstEnd(db); *sendbuf = result; return errorcode; }