Merge remote-tracking branch 'camodern/master'

* camodern/master:
  cas: ignore CA client version older than v4.4
  rsrv: remove !CA_V44() code
  rsrv: no ca exception response to UDP
  rsrv: ignore CA client version older than v4.4
  cas: honor DOREPLY for TCP searches
  cas: ignore echo and unexpected UDP
  rsrv: send channel create failure
  rsrv: UDP search ignore DOREPLY
  rsrv: ignore echo and unexpected UDP

Conflicts:
	src/ca/legacy/pcas/generic/casDGClient.cc
This commit is contained in:
Michael Davidsaver
2017-05-02 18:41:09 -04:00
5 changed files with 210 additions and 295 deletions

View File

@@ -28,7 +28,8 @@
#define CA_VERSION_STRING( MINOR_REVISION ) \
( capStrOfX ( CA_MAJOR_PROTOCOL_REVISION ) "." capStrOfX ( MINOR_REVISION ) )
#define CA_UKN_MINOR_VERSION 0u /* unknown minor version */
#if CA_MAJOR_PROTOCOL_REVISION == 4u
#define CA_MINIMUM_SUPPORTED_VERSION 4u
# define CA_VSUPPORTED(MINOR) ((MINOR)>=CA_MINIMUM_SUPPORTED_VERSION)
# define CA_V41(MINOR) ((MINOR)>=1u)
# define CA_V42(MINOR) ((MINOR)>=2u)
# define CA_V43(MINOR) ((MINOR)>=3u)
@@ -42,35 +43,6 @@
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
# define CA_V41(MINOR) ( 1u )
# define CA_V42(MINOR) ( 1u )
# define CA_V43(MINOR) ( 1u )
# define CA_V44(MINOR) ( 1u )
# define CA_V45(MINOR) ( 1u )
# define CA_V46(MINOR) ( 1u )
# define CA_V47(MINOR) ( 1u )
# define CA_V48(MINOR) ( 1u )
# define CA_V49(MINOR) ( 1u )
# define CA_V410(MINOR) ( 1u )
# define CA_V411(MINOR) ( 1u )
# define CA_V412(MINOR) ( 1u )
# define CA_V413(MINOR) ( 1u )
#else
# define CA_V41(MINOR) ( 0u )
# define CA_V42(MINOR) ( 0u )
# define CA_V43(MINOR) ( 0u )
# define CA_V44(MINOR) ( 0u )
# define CA_V45(MINOR) ( 0u )
# define CA_V46(MINOR) ( 0u )
# define CA_V47(MINOR) ( 0u )
# define CA_V48(MINOR) ( 0u )
# define CA_V49(MINOR) ( 0u )
# define CA_V410(MINOR) ( 0u )
# define CA_V411(MINOR) ( 0u )
# define CA_V412(MINOR) ( 0u )
# define CA_V413(MINOR) ( 0u )
#endif
/*
* These port numbers are only used if the CA repeater and

View File

@@ -51,7 +51,7 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
@@ -111,11 +111,13 @@ caStatus casDGClient::uknownMessageAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
}
return S_cas_badProtocol;
}
@@ -129,6 +131,16 @@ caStatus casDGClient::searchAction()
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
//
@@ -362,6 +374,15 @@ caStatus casDGClient::versionAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
if ( mp->m_count != 0 ) {
this->minor_version_number = static_cast <ca_uint16_t> ( mp->m_count );
if ( CA_V411 ( mp->m_count ) ) {

View File

@@ -338,6 +338,16 @@ caStatus casStrmClient::versionAction ( epicsGuard < casClientMutex > & )
return S_cas_badProtocol;
}
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
double tmp = mp->m_dataType - CA_PROTO_PRIORITY_MIN;
tmp *= epicsThreadPriorityCAServerHigh - epicsThreadPriorityCAServerLow;
tmp /= CA_PROTO_PRIORITY_MAX - CA_PROTO_PRIORITY_MIN;
@@ -1243,6 +1253,14 @@ caStatus casStrmClient :: searchResponse (
const pvExistReturn & retVal )
{
if ( retVal.getStatus() != pverExistsHere ) {
if (msg.m_dataType == DOREPLY ) {
long status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
msg.m_dataType, msg.m_count, msg.m_cid, msg.m_available, 0 );
if ( status == S_cas_success ) {
this->out.commitMsg ();
}
}
return S_cas_success;
}
@@ -1338,6 +1356,16 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
//
@@ -1407,11 +1435,8 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse ( guard, *mp, pver );
break;
case pverDoesNotExistHere:
status = S_cas_success;
status = this->searchResponse ( guard, *mp, pver );
break;
case pverAsyncCompletion:

View File

@@ -325,31 +325,12 @@ unsigned lineno
static int bad_udp_cmd_action ( caHdrLargeArray *mp,
void *pPayload, struct client *pClient )
{
log_header ("invalid (damaged?) request code from UDP",
pClient, mp, pPayload, 0);
if (CASDEBUG > 0)
log_header ("invalid (damaged?) request code from UDP",
pClient, mp, pPayload, 0);
return RSRV_ERROR;
}
/*
* udp_echo_action()
*/
static int udp_echo_action ( caHdrLargeArray *mp,
void *pPayload, struct client *pClient )
{
char *pPayloadOut;
int status;
SEND_LOCK ( pClient );
status = cas_copy_in_header ( pClient, mp->m_cmmd, mp->m_postsize,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available,
( void * ) &pPayloadOut );
if ( status == ECA_NORMAL ) {
memcpy ( pPayloadOut, pPayload, mp->m_postsize );
cas_commit_msg ( pClient, mp->m_postsize );
}
SEND_UNLOCK ( pClient );
return RSRV_OK;
}
/*
* bad_tcp_cmd_action()
*/
@@ -380,6 +361,13 @@ static int tcp_version_action ( caHdrLargeArray *mp, void *pPayload,
unsigned epicsPriorityNew;
unsigned epicsPrioritySelf;
client->minor_version_number = mp->m_count;
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore version from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
}
if ( mp->m_dataType > CA_PROTO_PRIORITY_MAX ) {
return RSRV_ERROR;
}
@@ -465,16 +453,6 @@ static void no_read_access_event ( struct client *pClient,
char *pPayloadOut;
int status;
/*
* continue to return an exception
* on failure to pre v41 clients
*/
if ( ! CA_V41 ( pClient->minor_version_number ) ) {
send_err ( &pevext->msg, ECA_GETFAIL, pClient,
RECORD_NAME ( pevext->pciu->dbch ) );
return;
}
/*
* New clients recv the status of the
* operation directly to the
@@ -514,7 +492,6 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
struct channel_in_use *pciu = pevext->pciu;
const int readAccess = asCheckGet ( pciu->asClientPVT );
int status;
int v41;
int autosize;
int local_fl = 0;
long item_count;
@@ -523,23 +500,7 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
SEND_LOCK ( pClient );
/*
* New clients recv the status of the
* operation directly to the
* event/put/get callback.
*
* The m_cid field in the protocol
* header is abused to carry the status,
* but get calls still use the
* m_cid field to identify the channel
*/
v41 = CA_V41 ( pClient->minor_version_number );
if ( v41 ) {
cid = ECA_NORMAL;
}
else {
cid = pciu->cid;
}
cid = ECA_NORMAL;
/* If the client has requested a zero element count we interpret this as a
* request for all avaiable elements. In this case we initialise the
@@ -590,35 +551,22 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
if (local_fl) db_delete_field_log(pfl);
if ( status < 0 ) {
/*
* I cant wait to redesign this protocol from scratch!
*/
if ( ! v41 ) {
/*
* old client & plain get
* continue to return an exception
* on failure
*/
send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( dbch ) );
}
else {
/* New clients recv the status of the operation directly to the
* event/put/get callback.
*
* Fetched value is set to zero in case they use it even when the
* status indicates failure -- unless the client selected autosizing
* data, in which case they'd better know what they're doing!
*
* The m_cid field in the protocol header is abused to carry the
* status */
if (autosize) {
payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
cas_set_header_count(pClient, 0);
}
memset ( pPayload, 0, payload_size );
cas_set_header_cid ( pClient, ECA_GETFAIL );
cas_commit_msg ( pClient, payload_size );
/* Clients recv the status of the operation directly to the
* event/put/get callback. (from CA_V41())
*
* Fetched value is set to zero in case they use it even when the
* status indicates failure -- unless the client selected autosizing
* data, in which case they'd better know what they're doing!
*
* The m_cid field in the protocol header is abused to carry the
* status */
if (autosize) {
payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
cas_set_header_count(pClient, 0);
}
memset ( pPayload, 0, payload_size );
cas_set_header_cid ( pClient, ECA_GETFAIL );
cas_commit_msg ( pClient, payload_size );
}
else {
int cacStatus = caNetConvert (
@@ -668,7 +616,6 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
ca_uint32_t payloadSize;
void *pPayload;
int status;
int v41;
int local_fl = 0;
db_field_log *pfl = NULL;
@@ -700,14 +647,8 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
/*
* verify read access
*/
v41 = CA_V41 ( pClient->minor_version_number );
if ( ! readAccess ) {
if ( v41 ) {
status = ECA_NORDACCESS;
}
else{
status = ECA_GETFAIL;
}
status = ECA_NORDACCESS;
send_err ( mp, status,
pClient, RECORD_NAME ( pciu->dbch ) );
SEND_UNLOCK ( pClient );
@@ -809,7 +750,6 @@ static int write_action ( caHdrLargeArray *mp,
void *pPayload, struct client *client )
{
struct channel_in_use *pciu;
int v41;
int status;
long dbStatus;
void *asWritePvt;
@@ -821,13 +761,7 @@ static int write_action ( caHdrLargeArray *mp,
}
if(!rsrvCheckPut(pciu)){
v41 = CA_V41(client->minor_version_number);
if(v41){
status = ECA_NOWTACCESS;
}
else{
status = ECA_PUTFAIL;
}
status = ECA_NOWTACCESS;
SEND_LOCK(client);
send_err(
mp,
@@ -1192,19 +1126,10 @@ static void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
static void access_rights_reply ( struct channel_in_use * pciu )
{
unsigned ar;
int v41;
int status;
assert ( pciu->client->proto!=IPPROTO_UDP );
/*
* noop if this is an old client
*/
v41 = CA_V41 ( pciu->client->minor_version_number );
if ( ! v41 ){
return;
}
ar = 0; /* none */
if ( asCheckGet ( pciu->asClientPVT ) ) {
ar |= CA_PROTO_ACCESS_RIGHT_READ;
@@ -1231,39 +1156,38 @@ static void access_rights_reply ( struct channel_in_use * pciu )
*/
static void claim_ciu_reply ( struct channel_in_use * pciu )
{
int v42 = CA_V42 ( pciu->client->minor_version_number );
int status;
ca_uint32_t nElem;
long dbElem;
access_rights_reply ( pciu );
if ( v42 ) {
int status;
ca_uint32_t nElem;
long dbElem;
SEND_LOCK ( pciu->client );
dbElem = dbChannelFinalElements(pciu->dbch);
if ( dbElem < 0 ) {
nElem = 0;
}
else {
if ( ! CA_V49 ( pciu->client->minor_version_number ) ) {
if ( dbElem >= 0xffff ) {
nElem = 0xfffe;
}
else {
nElem = (ca_uint32_t) dbElem;
}
SEND_LOCK ( pciu->client );
dbElem = dbChannelFinalElements(pciu->dbch);
if ( dbElem < 0 ) {
nElem = 0;
}
else {
if ( ! CA_V49 ( pciu->client->minor_version_number ) ) {
if ( dbElem >= 0xffff ) {
nElem = 0xfffe;
}
else {
nElem = (ca_uint32_t) dbElem;
}
}
status = cas_copy_in_header (
pciu->client, CA_PROTO_CREATE_CHAN, 0u,
dbChannelFinalCAType(pciu->dbch), nElem, pciu->cid,
pciu->sid, NULL );
if ( status == ECA_NORMAL ) {
cas_commit_msg ( pciu->client, 0u );
else {
nElem = (ca_uint32_t) dbElem;
}
SEND_UNLOCK(pciu->client);
}
status = cas_copy_in_header (
pciu->client, CA_PROTO_CREATE_CHAN, 0u,
dbChannelFinalCAType(pciu->dbch), nElem, pciu->cid,
pciu->sid, NULL );
if ( status == ECA_NORMAL ) {
cas_commit_msg ( pciu->client, 0u );
}
SEND_UNLOCK(pciu->client);
}
/*
@@ -1283,83 +1207,51 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
*/
client->minor_version_number = mp->m_available;
if (CA_V44(client->minor_version_number)) {
struct dbChannel *dbch;
char *pName = (char *) pPayload;
if (!CA_V44(client->minor_version_number))
return RSRV_ERROR; /* shouldn't actually get here due to VSUPPORTED test in camessage() */
/*
* check the sanity of the message
*/
if (mp->m_postsize<=1) {
log_header ( "empty PV name in UDP search request?",
client, mp, pPayload, 0 );
return RSRV_OK;
}
pName[mp->m_postsize-1] = '\0';
struct dbChannel *dbch;
char *pName = (char *) pPayload;
dbch = dbChannel_create (pName);
if (!dbch) {
return RSRV_OK;
}
DLOG ( 2, ("CAS: claim_ciu_action found '%s', type %d, count %d\n",
pName, dbChannelCAType(dbch), dbChannelElements(dbch)) );
pciu = casCreateChannel (
client,
dbch,
mp->m_cid);
if (!pciu) {
log_header ("no memory to create new channel",
client, mp, pPayload, 0);
SEND_LOCK(client);
send_err(mp,
ECA_ALLOCMEM,
client,
RECORD_NAME(dbch));
SEND_UNLOCK(client);
dbChannelDelete(dbch);
return RSRV_ERROR;
}
/*
* check the sanity of the message
*/
if (mp->m_postsize<=1) {
log_header ( "empty PV name in UDP search request?",
client, mp, pPayload, 0 );
return RSRV_OK;
}
else {
epicsMutexMustLock(client->chanListLock);
/*
* clients which dont claim their
* channel in use block prior to
* timeout must reconnect
*/
pciu = MPTOPCIU(mp);
if(!pciu){
errlogPrintf("CAS: client timeout disconnect id=%d\n",
mp->m_cid);
epicsMutexUnlock(client->chanListLock);
SEND_LOCK(client);
send_err(
mp,
ECA_INTERNAL,
client,
"old connect protocol timed out");
SEND_UNLOCK(client);
return RSRV_ERROR;
}
pName[mp->m_postsize-1] = '\0';
/*
* remove channel in use block from
* the UDP client where it could time
* out and place it on the client
* who is claiming it
*/
ellDelete(
&client->chanList,
&pciu->node);
epicsMutexUnlock(client->chanListLock);
dbch = dbChannel_create (pName);
if (!dbch) {
SEND_LOCK(client);
status = cas_copy_in_header ( client,
CA_PROTO_CREATE_CH_FAIL, 0, 0, 0, mp->m_cid, 0, NULL );
if (status == ECA_NORMAL)
cas_commit_msg ( client, 0u );
SEND_UNLOCK(client);
return RSRV_OK;
}
epicsMutexMustLock(client->chanListLock);
pciu->state = rsrvCS_pendConnectResp;
pciu->client = client;
ellAdd(&client->chanList, &pciu->node);
epicsMutexUnlock(client->chanListLock);
DLOG ( 2, ("CAS: claim_ciu_action found '%s', type %d, count %d\n",
pName, dbChannelCAType(dbch), dbChannelElements(dbch)) );
pciu = casCreateChannel (
client,
dbch,
mp->m_cid);
if (!pciu) {
log_header ("no memory to create new channel",
client, mp, pPayload, 0);
SEND_LOCK(client);
send_err(mp,
ECA_ALLOCMEM,
client,
RECORD_NAME(dbch));
SEND_UNLOCK(client);
dbChannelDelete(dbch);
return RSRV_ERROR;
}
/*
@@ -2212,14 +2104,18 @@ static void search_fail_reply ( caHdrLargeArray *mp, void *pPayload, struct clie
*/
static int udp_version_action ( caHdrLargeArray *mp, void *pPayload, struct client *client )
{
if ( mp->m_count != 0 ) {
client->minor_version_number = mp->m_count;
if ( CA_V411 ( mp->m_count ) ) {
client->seqNoOfReq = mp->m_cid;
}
else {
client->seqNoOfReq = 0;
}
client->minor_version_number = mp->m_count;
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore version from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
}
if ( CA_V411 ( mp->m_count ) ) {
client->seqNoOfReq = mp->m_cid;
}
else {
client->seqNoOfReq = 0;
}
return RSRV_OK;
}
@@ -2263,6 +2159,11 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client
size_t spaceNeeded;
size_t reasonableMonitorSpace = 10;
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore search from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
}
/*
* check the sanity of the message
*/
@@ -2276,8 +2177,6 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client
/* Exit quickly if channel not on this node */
if (dbChannelTest(pName)) {
DLOG ( 2, ( "CAS: Lookup for channel \"%s\" failed\n", pPayLoad ) );
if (mp->m_dataType == DOREPLY)
search_fail_reply ( mp, pPayload, client );
return RSRV_OK;
}
@@ -2289,10 +2188,7 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client
spaceNeeded = sizeof (struct channel_in_use) +
reasonableMonitorSpace * sizeof (struct event_ext);
if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) {
SEND_LOCK(client);
send_err ( mp, ECA_ALLOCMEM, client, "Server memory exhausted" );
SEND_UNLOCK(client);
return RSRV_OK;
return RSRV_ERROR;
}
/*
@@ -2311,36 +2207,8 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client
type = ca_server_port;
}
else {
struct dbChannel *dbch;
struct channel_in_use *pchannel;
dbch = dbChannel_create(pName);
if (!dbch) {
DLOG ( 2, ( "CAS: dbChannel Test of \"%s\" OK but Create failed\n", pName ) );
if (mp->m_dataType == DOREPLY)
search_fail_reply ( mp, pPayload, client );
return RSRV_OK;
}
pchannel = casCreateChannel ( client, dbch, mp->m_cid );
if (!pchannel) {
SEND_LOCK(client);
send_err ( mp, ECA_ALLOCMEM, client,
RECORD_NAME ( dbch ) );
SEND_UNLOCK ( client );
dbChannelDelete(dbch);
return RSRV_OK;
}
sid = pchannel->sid;
if ( dbChannelFinalElements(dbch) < 0 ) {
count = 0;
}
else if ( dbChannelFinalElements(dbch) > 0xffff ) {
count = 0xfffe;
}
else {
count = (ca_uint16_t) dbChannelFinalElements(dbch);
}
type = (ca_uint16_t) dbChannelFinalCAType(dbch);
/* shouldn't actually get here due to VSUPPORTED test */
return RSRV_ERROR;
}
SEND_LOCK ( client );
@@ -2378,6 +2246,11 @@ static int search_reply_tcp (
size_t spaceNeeded;
size_t reasonableMonitorSpace = 10;
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore search from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
}
/*
* check the sanity of the message
*/
@@ -2490,7 +2363,7 @@ static const pProtoStubUDP udpJumpTable[] =
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
udp_echo_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
@@ -2561,15 +2434,37 @@ int camessage ( struct client *client )
pBody = ( void * ) ( mp + 1 );
}
/* ignore deprecated clients, but let newer clients identify themselves. */
if (msg.m_cmmd!=CA_PROTO_VERSION && !CA_VSUPPORTED(client->minor_version_number)) {
if (client->proto==IPPROTO_TCP) {
/* log and error for too old clients, but keep the connection open to avoid a
* re-connect loop.
*/
send_err ( &msg, ECA_DEFUNCT, client,
"CAS: Client version %u too old", client->minor_version_number );
log_header ( "CAS: Client version too old",
client, &msg, 0, nmsg );
client->recvBytesToDrain = msgsize - bytes_left;
client->recv.stk = client->recv.cnt;
status = RSRV_OK;
} else {
/* silently ignore UDP from old clients */
status = RSRV_ERROR;
}
break;
}
/*
* disconnect clients that dont send 8 byte
* aligned payloads
*/
if ( msgsize & 0x7 ) {
send_err ( &msg, ECA_INTERNAL, client,
"CAS: Missaligned protocol rejected" );
log_header ( "CAS: Missaligned protocol rejected",
client, &msg, 0, nmsg );
if (client->proto==IPPROTO_TCP) {
send_err ( &msg, ECA_INTERNAL, client,
"CAS: Missaligned protocol rejected" );
log_header ( "CAS: Missaligned protocol rejected",
client, &msg, 0, nmsg );
}
status = RSRV_ERROR;
break;
}
@@ -2583,11 +2478,13 @@ int camessage ( struct client *client )
if ( msgsize > client->recv.maxstk ) {
casExpandRecvBuffer ( client, msgsize );
if ( msgsize > client->recv.maxstk ) {
send_err ( &msg, ECA_TOLARGE, client,
"CAS: Server unable to load large request message. Max bytes=%lu",
rsrvSizeofLargeBufTCP );
log_header ( "CAS: server unable to load large request message",
client, &msg, 0, nmsg );
if (client->proto==IPPROTO_TCP) {
send_err ( &msg, ECA_TOLARGE, client,
"CAS: Server unable to load large request message. Max bytes=%lu",
rsrvSizeofLargeBufTCP );
log_header ( "CAS: server unable to load large request message",
client, &msg, 0, nmsg );
}
assert ( client->recv.cnt <= client->recv.maxstk );
assert ( msgsize >= bytes_left );
client->recvBytesToDrain = msgsize - bytes_left;

View File

@@ -197,7 +197,7 @@ void cast_server(void *pParm)
client->recv.stk = 0ul;
epicsTimeGetCurrent(&client->time_at_last_recv);
client->minor_version_number = 0;
client->minor_version_number = CA_UKN_MINOR_VERSION;
client->seqNoOfReq = 0;
/*
@@ -247,7 +247,7 @@ void cast_server(void *pParm)
epicsPrintf ("CAS: message received at %s\n", buf);
}
}
else {
else if (CASDEBUG>0){
char buf[40];
ipAddrToDottedIP (&client->addr, buf, sizeof(buf));