You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
919 lines
33 KiB
919 lines
33 KiB
/***************************************************************************/
|
|
/* */
|
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
|
/* Protocol Version 2 */
|
|
/* */
|
|
/* File: slpd_v1process.c */
|
|
/* */
|
|
/* Abstract: Processes incoming SLP messages */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Please submit patches to http://www.openslp.org */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (C) 2000 Caldera Systems, Inc */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or without */
|
|
/* modification, are permitted provided that the following conditions are */
|
|
/* met: */
|
|
/* */
|
|
/* Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* */
|
|
/* Redistributions in binary form must reproduce the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer in */
|
|
/* the documentation and/or other materials provided with the */
|
|
/* distribution. */
|
|
/* */
|
|
/* Neither the name of Caldera Systems nor the names of its */
|
|
/* contributors may be used to endorse or promote products derived */
|
|
/* from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
/* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
|
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */
|
|
/* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
|
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
|
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
|
|
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
/* */
|
|
/***************************************************************************/
|
|
|
|
|
|
/*=========================================================================*/
|
|
/* slpd includes */
|
|
/*=========================================================================*/
|
|
#include "slpd_process.h"
|
|
#include "slpd_property.h"
|
|
#include "slpd_database.h"
|
|
#include "slpd_knownda.h"
|
|
#include "slpd_log.h"
|
|
|
|
|
|
/*=========================================================================*/
|
|
/* common code includes */
|
|
/*=========================================================================*/
|
|
#include "slp_xmalloc.h"
|
|
#include "slp_message.h"
|
|
#include "slp_v1message.h"
|
|
#include "slp_utf8.h"
|
|
#include "slp_compare.h"
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int v1ProcessDASrvRqst(struct sockaddr_in* peeraddr,
|
|
SLPMessage message,
|
|
SLPBuffer* sendbuf,
|
|
int errorcode)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
if (G_SlpdProperty.isDA)
|
|
{
|
|
if (message->body.srvrqst.scopelistlen == 0 ||
|
|
SLPIntersectStringList(message->body.srvrqst.scopelistlen,
|
|
message->body.srvrqst.scopelist,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes))
|
|
{
|
|
/* fill out real structure */
|
|
errorcode = SLPDKnownDAGenerateMyV1DAAdvert(errorcode,
|
|
message->header.encoding,
|
|
message->header.xid,
|
|
sendbuf);
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* don't return errorcodes to multicast messages */
|
|
if (errorcode != 0)
|
|
{
|
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
|
ISMCAST(peeraddr->sin_addr))
|
|
{
|
|
(*sendbuf)->end = (*sendbuf)->start;
|
|
return errorcode;
|
|
}
|
|
}
|
|
|
|
return errorcode;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int v1ProcessSrvRqst(struct sockaddr_in* peeraddr,
|
|
SLPMessage message,
|
|
SLPBuffer* sendbuf,
|
|
int errorcode)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int i;
|
|
int urllen;
|
|
int size = 0;
|
|
SLPDDatabaseSrvRqstResult* 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.srvrqst.prlistlen,
|
|
message->body.srvrqst.prlist,
|
|
G_SlpdProperty.interfacesLen,
|
|
G_SlpdProperty.interfaces))
|
|
{
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*------------------------------------------------*/
|
|
/* Check to to see if a this is a special SrvRqst */
|
|
/*------------------------------------------------*/
|
|
if (SLPCompareString(message->body.srvrqst.srvtypelen,
|
|
message->body.srvrqst.srvtype,
|
|
15,
|
|
"directory-agent") == 0)
|
|
{
|
|
errorcode = v1ProcessDASrvRqst(peeraddr, message, sendbuf, errorcode);
|
|
return errorcode;
|
|
}
|
|
|
|
/*------------------------------------*/
|
|
/* Make sure that we handle the scope */
|
|
/*------ -----------------------------*/
|
|
if (SLPIntersectStringList(message->body.srvrqst.scopelistlen,
|
|
message->body.srvrqst.scopelist,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes) != 0)
|
|
{
|
|
/*-------------------------------*/
|
|
/* Find services in the database */
|
|
/*-------------------------------*/
|
|
errorcode = SLPDDatabaseSrvRqstStart(message, &db);
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
RESPOND:
|
|
/*----------------------------------------------------------------*/
|
|
/* Do not send error codes or empty replies to multicast requests */
|
|
/*----------------------------------------------------------------*/
|
|
if (message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
if (errorcode != 0 || db->urlcount == 0)
|
|
{
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvrply */
|
|
/*-------------------------------------------------------------*/
|
|
size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes
|
|
for url count */
|
|
if (errorcode == 0)
|
|
{
|
|
for (i = 0; i < db->urlcount; i++)
|
|
{
|
|
urllen = INT_MAX;
|
|
errorcode = SLPv1ToEncoding(0,
|
|
&urllen,
|
|
message->header.encoding,
|
|
db->urlarray[i]->url,
|
|
db->urlarray[i]->urllen);
|
|
if (errorcode)
|
|
break;
|
|
size += urllen + 4; /* 2 bytes for lifetime, 2 bytes for urllen */
|
|
}
|
|
result = SLPBufferRealloc(result,size);
|
|
if (result == 0)
|
|
{
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Add the header */
|
|
/*----------------*/
|
|
/*version*/
|
|
*(result->start) = 1;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_SRVRPLY;
|
|
/*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 SrvRply */
|
|
/*-------------------------*/
|
|
result->curpos = result->start + 12;
|
|
/* error code*/
|
|
ToUINT16(result->curpos, errorcode);
|
|
result->curpos = result->curpos + 2;
|
|
if (errorcode == 0)
|
|
{
|
|
/* urlentry count */
|
|
ToUINT16(result->curpos, db->urlcount);
|
|
result->curpos = result->curpos + 2;
|
|
for (i = 0; i < db->urlcount; i++)
|
|
{
|
|
/* url-entry lifetime */
|
|
ToUINT16(result->curpos, db->urlarray[i]->lifetime);
|
|
result->curpos = result->curpos + 2;
|
|
/* url-entry url and urllen */
|
|
urllen = size;
|
|
errorcode = SLPv1ToEncoding(result->curpos + 2,
|
|
&urllen,
|
|
message->header.encoding,
|
|
db->urlarray[i]->url,
|
|
db->urlarray[i]->urllen);
|
|
ToUINT16(result->curpos, urllen);
|
|
result->curpos = result->curpos + 2 + urllen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* urlentry count */
|
|
ToUINT16(result->curpos, 0);
|
|
result->curpos = result->curpos + 2;
|
|
}
|
|
|
|
FINISHED:
|
|
|
|
SLPDDatabaseSrvRqstEnd(db);
|
|
|
|
*sendbuf = result;
|
|
|
|
return errorcode;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int v1ProcessSrvReg(struct sockaddr_in* peeraddr,
|
|
SLPMessage message,
|
|
SLPBuffer recvbuf,
|
|
SLPBuffer* sendbuf,
|
|
int errorcode)
|
|
/* */
|
|
/* Returns: non-zero if message should be silently dropped */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPBuffer result = *sendbuf;
|
|
|
|
/*--------------------------------------------------------------*/
|
|
/* If errorcode is set, we can not be sure that message is good */
|
|
/* Go directly to send response code also do not process mcast */
|
|
/* srvreg or srvdereg messages */
|
|
/*--------------------------------------------------------------*/
|
|
if (errorcode || message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
goto RESPOND;
|
|
}
|
|
|
|
/*------------------------------------*/
|
|
/* Make sure that we handle the scope */
|
|
/*------ -----------------------------*/
|
|
if (SLPIntersectStringList(message->body.srvreg.scopelistlen,
|
|
message->body.srvreg.scopelist,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes))
|
|
{
|
|
/*---------------------------------*/
|
|
/* put the service in the database */
|
|
/*---------------------------------*/
|
|
if (ISLOCAL(message->peer.sin_addr))
|
|
{
|
|
message->body.srvreg.source= SLP_REG_SOURCE_LOCAL;
|
|
}
|
|
else
|
|
{
|
|
message->body.srvreg.source = SLP_REG_SOURCE_REMOTE;
|
|
}
|
|
|
|
errorcode = SLPDDatabaseReg(message,recvbuf);
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
|
}
|
|
|
|
RESPOND:
|
|
/*--------------------------------------------------------------------*/
|
|
/* don't send back reply anything multicast SrvReg (set result empty) */
|
|
/*--------------------------------------------------------------------*/
|
|
if (message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvack */
|
|
/*------------------------------------------------------------*/
|
|
result = SLPBufferRealloc(result, 14);
|
|
if (result == 0)
|
|
{
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Add the header */
|
|
/*----------------*/
|
|
/*version*/
|
|
*(result->start) = 1;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_SRVACK;
|
|
/*length*/
|
|
ToUINT16(result->start + 2, 14);
|
|
/*flags - TODO set the flags correctly */
|
|
*(result->start + 4) = 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 the errorcode */
|
|
/*-------------------*/
|
|
ToUINT16(result->start + 12, errorcode);
|
|
|
|
FINISHED:
|
|
*sendbuf = result;
|
|
return errorcode;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int v1ProcessSrvDeReg(struct sockaddr_in* peeraddr,
|
|
SLPMessage message,
|
|
SLPBuffer* sendbuf,
|
|
int errorcode)
|
|
/* */
|
|
/* Returns: non-zero if message should be silently dropped */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPBuffer result = *sendbuf;
|
|
|
|
/*--------------------------------------------------------------*/
|
|
/* If errorcode is set, we can not be sure that message is good */
|
|
/* Go directly to send response code also do not process mcast */
|
|
/* srvreg or srvdereg messages */
|
|
/*--------------------------------------------------------------*/
|
|
if (errorcode || message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
goto RESPOND;
|
|
}
|
|
|
|
|
|
/*------------------------------------*/
|
|
/* Make sure that we handle the scope */
|
|
/*------------------------------------*/
|
|
if (SLPIntersectStringList(message->body.srvdereg.scopelistlen,
|
|
message->body.srvdereg.scopelist,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes))
|
|
{
|
|
/*--------------------------------------*/
|
|
/* remove the service from the database */
|
|
/*--------------------------------------*/
|
|
errorcode = SLPDDatabaseDeReg(message);
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
|
}
|
|
|
|
RESPOND:
|
|
/*---------------------------------------------------------*/
|
|
/* don't do anything multicast SrvDeReg (set result empty) */
|
|
/*---------------------------------------------------------*/
|
|
if (message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole srvack */
|
|
/*------------------------------------------------------------*/
|
|
result = SLPBufferRealloc(result, 14);
|
|
if (result == 0)
|
|
{
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Add the header */
|
|
/*----------------*/
|
|
/*version*/
|
|
*(result->start) = 1;
|
|
/*function id*/
|
|
*(result->start + 1) = SLP_FUNCT_SRVACK;
|
|
/*length*/
|
|
ToUINT16(result->start + 2, 14);
|
|
/*flags - TODO set the flags correctly */
|
|
*(result->start + 4) = 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 the errorcode */
|
|
/*-------------------*/
|
|
ToUINT16(result->start + 12, errorcode);
|
|
|
|
FINISHED:
|
|
*sendbuf = result;
|
|
return errorcode;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int v1ProcessAttrRqst(struct sockaddr_in* peeraddr,
|
|
SLPMessage message,
|
|
SLPBuffer* sendbuf,
|
|
int errorcode)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPDDatabaseAttrRqstResult* db = 0;
|
|
int attrlen = 0;
|
|
int size = 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.attrrqst.prlistlen,
|
|
message->body.attrrqst.prlist,
|
|
G_SlpdProperty.interfacesLen,
|
|
G_SlpdProperty.interfaces))
|
|
{
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
|
|
/*------------------------------------*/
|
|
/* Make sure that we handle the scope */
|
|
/*------ -----------------------------*/
|
|
if (SLPIntersectStringList(message->body.attrrqst.scopelistlen,
|
|
message->body.attrrqst.scopelist,
|
|
G_SlpdProperty.useScopesLen,
|
|
G_SlpdProperty.useScopes))
|
|
{
|
|
/*---------------------------------*/
|
|
/* Find attributes in the database */
|
|
/*---------------------------------*/
|
|
errorcode = SLPDDatabaseAttrRqstStart(message,&db);
|
|
}
|
|
else
|
|
{
|
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
|
}
|
|
|
|
RESPOND:
|
|
/*----------------------------------------------------------------*/
|
|
/* Do not send error codes or empty replies to multicast requests */
|
|
/*----------------------------------------------------------------*/
|
|
if (message->header.flags & SLP_FLAG_MCAST)
|
|
{
|
|
if (errorcode != 0 || db->attrlistlen == 0)
|
|
{
|
|
result->end = result->start;
|
|
goto FINISHED;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------*/
|
|
/* ensure the buffer is big enough to handle the whole attrrply */
|
|
/*--------------------------------------------------------------*/
|
|
size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes
|
|
for attr-list len */
|
|
if (errorcode == 0)
|
|
{
|
|
|
|
attrlen = INT_MAX;
|
|
errorcode = SLPv1ToEncoding(0, &attrlen,
|
|
message->header.encoding,
|
|
db->attrlist,
|
|
db->attrlistlen);
|
|
size += attrlen;
|
|
}
|
|
|
|
/*-------------------*/
|
|
/* Alloc the buffer */
|
|
/*-------------------*/
|
|
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_ATTRRPLY;
|
|
/*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 AttrRply */
|
|
/*--------------------------*/
|
|
result->curpos = result->start + 12;
|
|
/* error code*/
|
|
ToUINT16(result->curpos, errorcode);
|
|
result->curpos = result->curpos + 2;
|
|
if (errorcode == 0)
|
|
{
|
|
/* attr-list len */
|
|
ToUINT16(result->curpos, attrlen);
|
|
result->curpos = result->curpos + 2;
|
|
attrlen = size;
|
|
SLPv1ToEncoding(result->curpos, &attrlen,
|
|
message->header.encoding,
|
|
db->attrlist,
|
|
db->attrlistlen);
|
|
result->curpos = result->curpos + attrlen;
|
|
}
|
|
|
|
FINISHED:
|
|
*sendbuf = result;
|
|
if (db) SLPDDatabaseAttrRqstEnd(db);
|
|
|
|
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;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
int SLPDv1ProcessMessage(struct sockaddr_in* peeraddr,
|
|
SLPBuffer recvbuf,
|
|
SLPBuffer* sendbuf)
|
|
/* Processes the SLPv1 message and places the results in sendbuf */
|
|
/* */
|
|
/* peeraddr - the socket the message was received on */
|
|
/* */
|
|
/* recvbuf - message to process */
|
|
/* */
|
|
/* sendbuf - results of the processed message */
|
|
/* */
|
|
/* Returns - zero on success SLP_ERROR_PARSE_ERROR or */
|
|
/* SLP_ERROR_INTERNAL_ERROR on ENOMEM. */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPHeader header;
|
|
SLPMessage message;
|
|
int errorcode = 0;
|
|
|
|
if (!G_SlpdProperty.isDA)
|
|
{
|
|
/* SLPv1 messages are handled only by DAs */
|
|
errorcode = SLP_ERROR_VER_NOT_SUPPORTED;
|
|
return errorcode;
|
|
}
|
|
|
|
/* Parse just the message header the reset the buffer "curpos" pointer */
|
|
recvbuf->curpos = recvbuf->start;
|
|
errorcode = SLPv1MessageParseHeader(recvbuf, &header);
|
|
if (errorcode != 0)
|
|
{
|
|
return errorcode;
|
|
}
|
|
|
|
/* TRICKY: Duplicate SRVREG recvbufs *before* parsing them */
|
|
/* it because we are going to keep them in the */
|
|
if (header.functionid == SLP_FUNCT_SRVREG)
|
|
{
|
|
recvbuf = SLPBufferDup(recvbuf);
|
|
if (recvbuf == NULL)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Allocate the message descriptor */
|
|
message = SLPMessageAlloc();
|
|
if (message)
|
|
{
|
|
/* Parse the message and fill out the message descriptor */
|
|
errorcode = SLPv1MessageParseBuffer(peeraddr,recvbuf, message);
|
|
if (errorcode == 0)
|
|
{
|
|
/* Process messages based on type */
|
|
switch (message->header.functionid)
|
|
{
|
|
case SLP_FUNCT_SRVRQST:
|
|
errorcode = v1ProcessSrvRqst(peeraddr, message, sendbuf, errorcode);
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVREG:
|
|
errorcode = v1ProcessSrvReg(peeraddr,
|
|
message,
|
|
recvbuf,
|
|
sendbuf,
|
|
errorcode);
|
|
if (errorcode == 0)
|
|
{
|
|
SLPDKnownDAEcho(message, recvbuf);
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVDEREG:
|
|
errorcode = v1ProcessSrvDeReg(peeraddr, message, sendbuf, errorcode);
|
|
if (errorcode == 0)
|
|
{
|
|
SLPDKnownDAEcho(message, recvbuf);
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_ATTRRQST:
|
|
errorcode = v1ProcessAttrRqst(peeraddr, message, sendbuf, errorcode);
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVTYPERQST:
|
|
errorcode = v1ProcessSrvTypeRqst(peeraddr, message, sendbuf, errorcode);
|
|
break;
|
|
|
|
case SLP_FUNCT_DAADVERT:
|
|
/* we are a SLPv2 DA, ignore other v1 DAs */
|
|
(*sendbuf)->end = (*sendbuf)->start;
|
|
break;
|
|
|
|
default:
|
|
/* Should never happen... but we're paranoid */
|
|
errorcode = SLP_ERROR_PARSE_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (header.functionid == SLP_FUNCT_SRVREG)
|
|
{
|
|
/* TRICKY: Do not free the message descriptor for SRVREGs */
|
|
/* because we are keeping them in the database */
|
|
/* unless there is an error then we free memory */
|
|
if (errorcode)
|
|
{
|
|
SLPMessageFree(message);
|
|
SLPBufferFree(recvbuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SLPMessageFree(message);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* out of memory */
|
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
return errorcode;
|
|
}
|