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; /*