From 16c419350b9184142166a559b845ca468e4e6b0c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 10:41:39 -0400 Subject: [PATCH 1/9] rsrv: ignore echo and unexpected UDP Ignore UDP echo. By default, don't log unexpected/invalid UDP messages. --- src/ioc/rsrv/camessage.c | 27 ++++----------------------- src/ioc/rsrv/cast_server.c | 2 +- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index b5c265ca6..98331abba 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -324,31 +324,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() */ @@ -2488,7 +2469,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, diff --git a/src/ioc/rsrv/cast_server.c b/src/ioc/rsrv/cast_server.c index b6bed8484..d87428b49 100644 --- a/src/ioc/rsrv/cast_server.c +++ b/src/ioc/rsrv/cast_server.c @@ -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)); From 802f29df478d510b1548c4c361bfd18190de046e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 10:46:21 -0400 Subject: [PATCH 2/9] rsrv: UDP search ignore DOREPLY Don't send notice of failure for lookup via. UDP. --- src/ioc/rsrv/camessage.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 98331abba..1b00aaace 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -2255,8 +2255,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; } @@ -2296,8 +2294,6 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client 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 ); From 8992d5a593781216e2faa8b0a4bf983007d5221e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 12:09:33 -0400 Subject: [PATCH 3/9] rsrv: send channel create failure --- src/ioc/rsrv/camessage.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 1b00aaace..3765aa47c 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -1278,6 +1278,12 @@ static int claim_ciu_action ( caHdrLargeArray *mp, 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; } From 4c2b8819cdcb115eca47a1dd2d797baf13f3b235 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 11:46:28 -0400 Subject: [PATCH 4/9] cas: ignore echo and unexpected UDP Ignore UDP echo. By default, don't log unexpected/invalid UDP messages. --- src/ca/legacy/pcas/generic/casDGClient.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ca/legacy/pcas/generic/casDGClient.cc b/src/ca/legacy/pcas/generic/casDGClient.cc index 4f1f41ecb..ffcfa69ff 100644 --- a/src/ca/legacy/pcas/generic/casDGClient.cc +++ b/src/ca/legacy/pcas/generic/casDGClient.cc @@ -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; } From 2dd16f43621f62e0d3319cbafbcdabffc587349f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 31 Jul 2016 15:10:36 -0400 Subject: [PATCH 5/9] cas: honor DOREPLY for TCP searches --- src/ca/legacy/pcas/generic/casStrmClient.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ca/legacy/pcas/generic/casStrmClient.cc b/src/ca/legacy/pcas/generic/casStrmClient.cc index 6b1de3629..015192769 100644 --- a/src/ca/legacy/pcas/generic/casStrmClient.cc +++ b/src/ca/legacy/pcas/generic/casStrmClient.cc @@ -1219,6 +1219,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; } @@ -1383,11 +1391,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: From 95fd255dd6b888b90624547165062b8a97278fab Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 10:35:49 -0400 Subject: [PATCH 6/9] rsrv: ignore CA client version older than v4.4 RSRV ignore search and version messages from CA minor versions older than 4. --- src/ca/client/caProto.h | 32 ++---------------- src/ioc/rsrv/camessage.c | 67 ++++++++++++++++++++++++++++++++------ src/ioc/rsrv/cast_server.c | 2 +- 3 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/ca/client/caProto.h b/src/ca/client/caProto.h index f61f52e08..781c89b34 100644 --- a/src/ca/client/caProto.h +++ b/src/ca/client/caProto.h @@ -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 diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 3765aa47c..b64c73af9 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -360,6 +360,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; } @@ -2197,8 +2204,14 @@ static void search_fail_reply ( caHdrLargeArray *mp, void *pPayload, struct clie */ static int udp_version_action ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { + 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_count != 0 ) { - client->minor_version_number = mp->m_count; if ( CA_V411 ( mp->m_count ) ) { client->seqNoOfReq = mp->m_cid; } @@ -2248,6 +2261,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 */ @@ -2359,6 +2377,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 */ @@ -2542,15 +2565,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; } @@ -2564,11 +2609,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; diff --git a/src/ioc/rsrv/cast_server.c b/src/ioc/rsrv/cast_server.c index d87428b49..be5ec15c6 100644 --- a/src/ioc/rsrv/cast_server.c +++ b/src/ioc/rsrv/cast_server.c @@ -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; /* From caf70216d378eba29391de242472394b185d3f1c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 31 Jul 2016 19:35:25 -0400 Subject: [PATCH 7/9] rsrv: no ca exception response to UDP --- src/ioc/rsrv/camessage.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index b64c73af9..769389d50 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -2290,10 +2290,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; } /* From da78e01e8955448ed1e7cb384a37ddddcf6f0ca0 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 31 Jul 2016 19:49:08 -0400 Subject: [PATCH 8/9] rsrv: remove !CA_V44() code Remove code supporting deprecated CA minor versions < 3 --- src/ioc/rsrv/camessage.c | 308 +++++++++++---------------------------- 1 file changed, 89 insertions(+), 219 deletions(-) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 769389d50..720289647 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -452,16 +452,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 @@ -501,7 +491,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; @@ -510,23 +499,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 @@ -577,35 +550,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 ( @@ -655,7 +615,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; @@ -686,14 +645,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 ); @@ -795,7 +748,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; @@ -807,13 +759,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, @@ -1178,19 +1124,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; @@ -1217,39 +1154,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); } /* @@ -1269,89 +1205,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) { - 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; - } - - 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; } /* @@ -2211,13 +2109,11 @@ static int udp_version_action ( caHdrLargeArray *mp, void *pPayload, struct clie return RSRV_ERROR; } - if ( mp->m_count != 0 ) { - if ( CA_V411 ( mp->m_count ) ) { - client->seqNoOfReq = mp->m_cid; - } - else { - client->seqNoOfReq = 0; - } + if ( CA_V411 ( mp->m_count ) ) { + client->seqNoOfReq = mp->m_cid; + } + else { + client->seqNoOfReq = 0; } return RSRV_OK; } @@ -2309,34 +2205,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 ) ); - 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 ); From ebfaca8228be9da994cd2186eeab4a8dd5212f77 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Jul 2016 11:45:42 -0400 Subject: [PATCH 9/9] cas: ignore CA client version older than v4.4 CAS ignore search and version messages from CA minor versions older than 4.4. --- src/ca/legacy/pcas/generic/casDGClient.cc | 19 +++++++++++++++++++ src/ca/legacy/pcas/generic/casStrmClient.cc | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/ca/legacy/pcas/generic/casDGClient.cc b/src/ca/legacy/pcas/generic/casDGClient.cc index ffcfa69ff..0760c2e24 100644 --- a/src/ca/legacy/pcas/generic/casDGClient.cc +++ b/src/ca/legacy/pcas/generic/casDGClient.cc @@ -131,6 +131,16 @@ caStatus casDGClient::searchAction() const char *pChanName = static_cast ( 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 // @@ -368,6 +378,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 ( mp->m_count ); if ( CA_V411 ( mp->m_count ) ) { diff --git a/src/ca/legacy/pcas/generic/casStrmClient.cc b/src/ca/legacy/pcas/generic/casStrmClient.cc index 015192769..eed6543a5 100644 --- a/src/ca/legacy/pcas/generic/casStrmClient.cc +++ b/src/ca/legacy/pcas/generic/casStrmClient.cc @@ -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; @@ -1322,6 +1332,16 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard ) const char *pChanName = static_cast ( 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 //