#ifdef EXTRA_MSGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include "mslp_sd.h"
#include "slp.h"
#include "mslp.h"
#include "mslp_dat.h"
#include "mslpd_store.h"
#include "mslpd.h"
#include "mslpd_mask.h"
#include "mslpd_parse.h"
static SLPInternalError optrply_out(Slphdr *pslphdr, int replytype, SLPInternalError err,
char **ppcOutBuf, int *piOutSz,
const char *pcResult, int extra);
static int tag_list_includes(const char *pcTagList, const char *pcTag);
static SLPInternalError srvtyperqst_in(Slphdr *pslph, const char *pcInBuf, int iInSz,
char **ppcPRL, char **ppcNA, char **ppcSL) {
SLPInternalError err;
int offset = HDRLEN + strlen(pslph->h_pcLangTag);
int iNALen = 0;
*ppcPRL = NULL;
*ppcNA = NULL;
*ppcSL = NULL;
if ((err = get_string(pcInBuf, iInSz, &offset, ppcPRL)) < 0)
goto srvtyperqst_in_fail;
if ((err = get_sht(pcInBuf, iInSz, &offset, &iNALen)) < 0)
goto srvtyperqst_in_fail;
if (iNALen == 0xffff) {
*ppcNA = safe_malloc(2,"*",1);
if( !*ppcNA ) return SLP_MEMORY_ALLOC_FAILED;
} else {
offset -= 2;
if ((err = get_string(pcInBuf, iInSz, &offset, ppcNA)) < 0)
goto srvtyperqst_in_fail;
}
if ((err = get_string(pcInBuf, iInSz, &offset, ppcSL)) < 0)
goto srvtyperqst_in_fail;
return SLP_OK;
srvtyperqst_in_fail:
SLPFree(*ppcPRL); *ppcPRL = NULL;
SLPFree(*ppcNA); *ppcNA = NULL;
SLPFree(*ppcSL); *ppcSL = NULL;
return err;
}
int opt_type_request(SAState *psa, Slphdr *pslphdr, const char *pcInBuf,
int iInSz, char **ppcOutBuf, int *piOutSz,int *piGot) {
char *pcList = safe_malloc(1,0,0);
char *pcPRList=NULL, *pcNA = NULL, *pcSList = NULL;
const char *pcSrvtypes = SLPGetProperty("com.sun.slp.saSrvTypes");
int err = 0;
if( !pcList || !psa || !pslphdr || !pcInBuf || !ppcOutBuf || !piOutSz) return SLP_PARSE_ERROR;
*ppcOutBuf = NULL;
*piOutSz = 0;
*piGot = 0;
if (pcSrvtypes == NULL) {
pcSrvtypes = "";
}
if ((err=srvtyperqst_in(pslphdr,pcInBuf,iInSz,&pcPRList,&pcNA,&pcSList))<0){
SLP_LOG( SLP_LOG_DROP,"opt_type_request: drop request due to parse in error");
if ((err = optrply_out(pslphdr,SRVTYPERPLY,SLP_PARSE_ERROR,
ppcOutBuf,piOutSz,"", 0)) != SLP_OK) {
LOG(SLP_LOG_ERR,"opt_type_request: could not serialize parse error");
}
err = SLP_PARSE_ERROR;
} else if (on_PRList(psa,pcPRList)) {
SLP_LOG( SLP_LOG_DROP,"opt_type_request: drop request which is on my PRList");
SLPFree(pcList);
SLPFree(pcPRList);
SLPFree(pcSList);
SLPFree(pcNA);
return SLP_OK;
} else if (!pcPRList || !pcNA || !pcSList ) {
SLP_LOG( SLP_LOG_DROP,"opt_type_request: request is malformed - missing values");
if ((err = optrply_out(pslphdr,SRVTYPERPLY,SLP_PARSE_ERROR,
ppcOutBuf,piOutSz,"", 0)) != SLP_OK) {
LOG(SLP_LOG_ERR,"opt_type_request: could not serialize missing val error");
}
err = SLP_PARSE_ERROR;
} else if (!list_intersection(pcSList,SLPGetProperty("net.slp.useScopes"))){
SLP_LOG( SLP_LOG_DROP,"opt_type_request: drop request not on my scope list");
if ((err = optrply_out(pslphdr,SRVTYPERPLY,SLP_SCOPE_NOT_SUPPORTED,
ppcOutBuf,piOutSz,"", 0)) != SLP_OK) {
LOG(SLP_LOG_ERR,"opt_type_request: could not serialize scope supp. error");
}
err = SLP_SCOPE_NOT_SUPPORTED;
} else {
int iListLen = 0;
char *pcSrvtype;
char *pcNAVal;
int loop;
for (loop = 0; loop < psa->store.size; loop++) {
if (list_intersection(pcSList,psa->store.scope[loop]) == 0) {
continue;
}
pcSrvtype = psa->store.srvtype[loop];
pcNAVal = strchr(pcSrvtype,(int) '.');
if (pcNA[0] == '*') {
list_merge(pcSrvtype,&pcList,&iListLen,CHECK);
*piGot += 1;
} else if (pcNAVal != NULL) {
pcNAVal++;
if (!SDstrncasecmp(pcNAVal, pcNA,strlen(pcNA)) &&
(strlen(pcNAVal) == strlen(pcNA) ||
pcNAVal[strlen(pcNA)] == ':')) {
list_merge(pcSrvtype,&pcList,&iListLen,CHECK);
*piGot += 1;
}
} else {
if (pcNA[0] == '\0') {
list_merge(pcSrvtype,&pcList,&iListLen,CHECK);
*piGot += 1;
}
}
}
err = optrply_out(pslphdr, SRVTYPERPLY, (SLPInternalError) err,
ppcOutBuf, piOutSz, pcList, 0);
}
SLPFree(pcList);
SLPFree(pcPRList);
SLPFree(pcSList);
SLPFree(pcNA);
if (err == 0) return 0;
else return (int) err;
}
int opt_attr_request(SAState *psa, Slphdr *pslphdr, const char *pcInBuf,
int iInSz, char **ppcOutBuf, int *piOutSz, int *piGot) {
char *pcPRList=NULL, *pcSrv = NULL, *pcSList = NULL, *pcTagList = NULL;
SLPInternalError err = SLP_OK;
int result = 0;
if (!psa || !pslphdr || !pcInBuf || !ppcOutBuf || !piOutSz) return SLP_PARSE_ERROR;
*ppcOutBuf = NULL;
*piOutSz = 0;
*piGot = 0;
if ((err = srvrqst_in(pslphdr,pcInBuf,iInSz,&pcPRList,
&pcSrv,&pcSList,&pcTagList))<0){
SLP_LOG( SLP_LOG_DROP,"opt_attr_request: drop request due to parse in error");
return SLP_OK;
} else if (on_PRList(psa,pcPRList)) {
SLP_LOG( SLP_LOG_DROP,"opt_attr_request: drop request which is on my PRList");
return SLP_OK;
} if (!list_intersection(pcSList,SLPGetProperty("net.slp.useScopes"))){
SLP_LOG( SLP_LOG_DROP,"opt_attr_request: drop request not on my scope list");
return SLP_OK;
} else {
MslpHashtable *pmht = mslp_hash_init();
MslpHashbucket *pb;
char *pcResult = safe_malloc(1,0,0);
int iSz = 0;
int i, j;
int iRetval;
if( !pcResult ) return SLP_MEMORY_ALLOC_FAILED;
for (i = 0; (err == SLP_OK) && (i < psa->store.size); i++) {
if ((iRetval=match_langtag(psa->store.lang[i],pslphdr->h_pcLangTag))==0) {
continue;
} else if (iRetval != 1) {
mslplog(SLP_LOG_DROP,"opt_attr_request: bad language in request",
pslphdr->h_pcLangTag);
continue;
}
if (!list_intersection(psa->store.scope[i],pcSList)) {
continue;
}
if ((iRetval=match_srvtype(pcSrv,psa->store.url[i]))==0) {
continue;
} else if (iRetval != 1) {
mslplog(SLP_LOG_DROP,"opt_attr_request: bad servtype in request",pcSrv);
continue;
}
for (j = 0; (err == SLP_OK) && (psa->store.tag[i][j]); j++) {
char *pcVals;
const char *pcValList;
int returnval = tag_list_includes(pcTagList,psa->store.tag[i][j]);
if (pcTagList[0] != '\0' && returnval == 0) {
continue;
} else if (returnval != SLP_OK && returnval != 1) {
SLP_LOG( SLP_LOG_DEBUG,"opt_attr_request: could not compare tag lists");
err = (SLPInternalError) returnval;
break;
}
if ((pcVals = serialize_values(&(psa->store),i,j)) == NULL) {
continue;
}
if ((pcValList = mslp_hash_find(pmht, psa->store.tag[i][j])) == NULL) {
mslp_hash_add(pmht, psa->store.tag[i][j], pcVals);
} else {
int iValSz = strlen(pcVals);
list_merge(pcValList,&pcVals,&iValSz,CHECK);
mslp_hash_add(pmht, psa->store.tag[i][j], pcVals);
}
SLPFree(pcVals);
}
}
for (result = 0 ; (err == 0) && (result < NUMBUCKETS); result++) {
char *pcItem;
pb = pmht->bucket[result];
while (pb) {
if (pb->pcVal[0] == '\0') {
list_merge(pb->pcKey, &pcResult, &iSz, NO_CHECK);
*piGot += 1;
} else {
pcItem = safe_malloc(strlen(pb->pcKey) +strlen(pb->pcVal) +4, 0, 0);
if( !pcItem ) return SLP_PARSE_ERROR;
sprintf(pcItem,"(%s=%s)",pb->pcKey,pb->pcVal);
list_merge(pcItem, &pcResult, &iSz, NO_CHECK);
SLPFree(pcItem);
*piGot += 1;
}
pb = pb->pBucketNext;
}
}
err = optrply_out(pslphdr, ATTRRPLY, (SLPInternalError) err,
ppcOutBuf, piOutSz, pcResult, 1);
SLPFree(pcResult);
}
if (err == 0) return 0;
else return -1;
}
static SLPInternalError optrply_out(Slphdr *pslphdr, int replytype, SLPInternalError err,
char **ppcOutBuf, int *piOutSz,
const char *pcResult, int extra) {
char* endPtr = NULL;
int iMTU = (SLPGetProperty("net.slp.MTU"))?strtol(SLPGetProperty("net.slp.MTU"),&endPtr,10):1400;
int iOverflow = 0;
int iIsMcast = (pslphdr->h_usFlags & MCASTFLAG)?1:0;
int hdrsz = HDRLEN + strlen(pslphdr->h_pcLangTag);
int offset = 0;
*piOutSz = hdrsz + 2 +
strlen(pcResult) + 2 + extra +
1;
if (iIsMcast && *piOutSz >= iMTU) {
*piOutSz = hdrsz + 2;
iOverflow = 1;
}
*ppcOutBuf = safe_malloc(*piOutSz, 0, 0);
if( !*ppcOutBuf ) return SLP_PARSE_ERROR;
SETVER(*ppcOutBuf,2);
SETFUN(*ppcOutBuf,replytype);
SETLEN(*ppcOutBuf,*piOutSz);
SETLANG(*ppcOutBuf,pslphdr->h_pcLangTag);
SETXID(*ppcOutBuf,pslphdr->h_usXID);
if (iOverflow) {
SETFLAGS(*ppcOutBuf,OVERFLOWFLAG);
return SLP_OK;
}
offset = hdrsz;
SETSHT(*ppcOutBuf,api2slp(err),offset); offset += 2;
if ((err=add_string(*ppcOutBuf,*piOutSz,pcResult,&offset))!=SLP_OK) {
SLP_LOG( SLP_LOG_DEBUG,"optrply_out: could not add_string, should never happen!");
offset = hdrsz;
SETSHT(*ppcOutBuf,api2slp(SLP_PARSE_ERROR),offset);
*piOutSz = hdrsz+2;
SETLEN(*ppcOutBuf,*piOutSz);
return SLP_PARSE_ERROR;
}
return SLP_OK;
}
static int tag_list_includes(const char *pcTagList, const char *pcTag) {
char *pcTagQuery;
char cDelim;
int offset = 0;
int result = 0;
SLPInternalError err = SLP_OK;
int iErr = 0;
if (!pcTagList || !pcTag) return SLP_PARSE_ERROR;
if (pcTagList[0] == '\0' && pcTag[0] == '\0') return 1;
while ((pcTagQuery= get_next_string(",",pcTagList,&offset,&cDelim)) != NULL){
if ((iErr = isWildMatch(pcTagQuery,pcTag)) != 0) {
if (iErr < 0) {
err = (SLPInternalError) iErr;
result = 0;
} else {
result = 1;
}
break;
}
SLPFree(pcTagQuery);
pcTagQuery = NULL;
}
SLPFree(pcTagQuery);
if (err != SLP_OK) return err;
return result;
}
#ifndef NDEBUG
int opt_tag_list_includes(const char *pc1, const char *pc2) {
return tag_list_includes(pc1,pc2);
}
SLPInternalError opt_optrply_out(Slphdr *pslphdr, int replytype,
SLPInternalError err, char **ppcOutBuf,
int *piOutSz, const char *pcResult, int extra) {
return optrply_out(pslphdr,replytype,err,
ppcOutBuf,piOutSz,pcResult,extra);
}
#endif
#endif