@@ -400,6 +400,24 @@ smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
400400 return true;
401401}
402402
403+ /* check arriving CLC decline */
404+ static bool
405+ smc_clc_msg_decl_valid (struct smc_clc_msg_decline * dclc )
406+ {
407+ struct smc_clc_msg_hdr * hdr = & dclc -> hdr ;
408+
409+ if (hdr -> typev1 != SMC_TYPE_R && hdr -> typev1 != SMC_TYPE_D )
410+ return false;
411+ if (hdr -> version == SMC_V1 ) {
412+ if (ntohs (hdr -> length ) != sizeof (struct smc_clc_msg_decline ))
413+ return false;
414+ } else {
415+ if (ntohs (hdr -> length ) != sizeof (struct smc_clc_msg_decline_v2 ))
416+ return false;
417+ }
418+ return true;
419+ }
420+
403421static void smc_clc_fill_fce (struct smc_clc_first_contact_ext * fce , int * len )
404422{
405423 memset (fce , 0 , sizeof (* fce ));
@@ -441,9 +459,9 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
441459 break ;
442460 case SMC_CLC_DECLINE :
443461 dclc = (struct smc_clc_msg_decline * )clcm ;
444- if (ntohs ( dclc -> hdr . length ) != sizeof ( * dclc ))
462+ if (! smc_clc_msg_decl_valid ( dclc ))
445463 return false;
446- trl = & dclc -> trl ;
464+ check_trl = false ;
447465 break ;
448466 default :
449467 return false;
@@ -742,15 +760,16 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
742760/* send CLC DECLINE message across internal TCP socket */
743761int smc_clc_send_decline (struct smc_sock * smc , u32 peer_diag_info , u8 version )
744762{
745- struct smc_clc_msg_decline dclc ;
763+ struct smc_clc_msg_decline * dclc_v1 ;
764+ struct smc_clc_msg_decline_v2 dclc ;
746765 struct msghdr msg ;
766+ int len , send_len ;
747767 struct kvec vec ;
748- int len ;
749768
769+ dclc_v1 = (struct smc_clc_msg_decline * )& dclc ;
750770 memset (& dclc , 0 , sizeof (dclc ));
751771 memcpy (dclc .hdr .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
752772 dclc .hdr .type = SMC_CLC_DECLINE ;
753- dclc .hdr .length = htons (sizeof (struct smc_clc_msg_decline ));
754773 dclc .hdr .version = version ;
755774 dclc .os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX ;
756775 dclc .hdr .typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR ) ?
@@ -760,14 +779,22 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version)
760779 memcpy (dclc .id_for_peer , local_systemid ,
761780 sizeof (local_systemid ));
762781 dclc .peer_diagnosis = htonl (peer_diag_info );
763- memcpy (dclc .trl .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
782+ if (version == SMC_V1 ) {
783+ memcpy (dclc_v1 -> trl .eyecatcher , SMC_EYECATCHER ,
784+ sizeof (SMC_EYECATCHER ));
785+ send_len = sizeof (* dclc_v1 );
786+ } else {
787+ memcpy (dclc .trl .eyecatcher , SMC_EYECATCHER ,
788+ sizeof (SMC_EYECATCHER ));
789+ send_len = sizeof (dclc );
790+ }
791+ dclc .hdr .length = htons (send_len );
764792
765793 memset (& msg , 0 , sizeof (msg ));
766794 vec .iov_base = & dclc ;
767- vec .iov_len = sizeof (struct smc_clc_msg_decline );
768- len = kernel_sendmsg (smc -> clcsock , & msg , & vec , 1 ,
769- sizeof (struct smc_clc_msg_decline ));
770- if (len < 0 || len < sizeof (struct smc_clc_msg_decline ))
795+ vec .iov_len = send_len ;
796+ len = kernel_sendmsg (smc -> clcsock , & msg , & vec , 1 , send_len );
797+ if (len < 0 || len < send_len )
771798 len = - EPROTO ;
772799 return len > 0 ? 0 : len ;
773800}
0 commit comments