27
27
28
28
#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
29
29
#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
30
+ #define SMC_CLC_RECV_BUF_LEN 100
30
31
31
32
/* eye catcher "SMCR" EBCDIC for CLC messages */
32
33
static const char SMC_EYECATCHER [4 ] = {'\xe2' , '\xd4' , '\xc3' , '\xd9' };
@@ -36,7 +37,7 @@ static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
36
37
/* check if received message has a correct header length and contains valid
37
38
* heading and trailing eyecatchers
38
39
*/
39
- static bool smc_clc_msg_hdr_valid (struct smc_clc_msg_hdr * clcm )
40
+ static bool smc_clc_msg_hdr_valid (struct smc_clc_msg_hdr * clcm , bool check_trl )
40
41
{
41
42
struct smc_clc_msg_proposal_prefix * pclc_prfx ;
42
43
struct smc_clc_msg_accept_confirm * clc ;
@@ -49,12 +50,9 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
49
50
return false;
50
51
switch (clcm -> type ) {
51
52
case SMC_CLC_PROPOSAL :
52
- if (clcm -> path != SMC_TYPE_R && clcm -> path != SMC_TYPE_D &&
53
- clcm -> path != SMC_TYPE_B )
54
- return false;
55
53
pclc = (struct smc_clc_msg_proposal * )clcm ;
56
54
pclc_prfx = smc_clc_proposal_get_prefix (pclc );
57
- if (ntohs (pclc -> hdr .length ) !=
55
+ if (ntohs (pclc -> hdr .length ) <
58
56
sizeof (* pclc ) + ntohs (pclc -> iparea_offset ) +
59
57
sizeof (* pclc_prfx ) +
60
58
pclc_prfx -> ipv6_prefixes_cnt *
@@ -86,7 +84,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
86
84
default :
87
85
return false;
88
86
}
89
- if (memcmp (trl -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )) &&
87
+ if (check_trl &&
88
+ memcmp (trl -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )) &&
90
89
memcmp (trl -> eyecatcher , SMCD_EYECATCHER , sizeof (SMCD_EYECATCHER )))
91
90
return false;
92
91
return true;
@@ -276,7 +275,8 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
276
275
struct msghdr msg = {NULL , 0 };
277
276
int reason_code = 0 ;
278
277
struct kvec vec = {buf , buflen };
279
- int len , datlen ;
278
+ int len , datlen , recvlen ;
279
+ bool check_trl = true;
280
280
int krflags ;
281
281
282
282
/* peek the first few bytes to determine length of data to receive
@@ -320,27 +320,46 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
320
320
}
321
321
datlen = ntohs (clcm -> length );
322
322
if ((len < sizeof (struct smc_clc_msg_hdr )) ||
323
- (datlen > buflen ) ||
324
- (clcm -> version != SMC_CLC_V1 ) ||
325
- (clcm -> path != SMC_TYPE_R && clcm -> path != SMC_TYPE_D &&
326
- clcm -> path != SMC_TYPE_B ) ||
323
+ (clcm -> version < SMC_CLC_V1 ) ||
327
324
((clcm -> type != SMC_CLC_DECLINE ) &&
328
325
(clcm -> type != expected_type ))) {
329
326
smc -> sk .sk_err = EPROTO ;
330
327
reason_code = - EPROTO ;
331
328
goto out ;
332
329
}
333
330
331
+ if (clcm -> type == SMC_CLC_PROPOSAL && clcm -> path == SMC_TYPE_N )
332
+ reason_code = SMC_CLC_DECL_VERSMISMAT ; /* just V2 offered */
333
+
334
334
/* receive the complete CLC message */
335
335
memset (& msg , 0 , sizeof (struct msghdr ));
336
- iov_iter_kvec (& msg .msg_iter , READ , & vec , 1 , datlen );
336
+ if (datlen > buflen ) {
337
+ check_trl = false;
338
+ recvlen = buflen ;
339
+ } else {
340
+ recvlen = datlen ;
341
+ }
342
+ iov_iter_kvec (& msg .msg_iter , READ , & vec , 1 , recvlen );
337
343
krflags = MSG_WAITALL ;
338
344
len = sock_recvmsg (smc -> clcsock , & msg , krflags );
339
- if (len < datlen || !smc_clc_msg_hdr_valid (clcm )) {
345
+ if (len < recvlen || !smc_clc_msg_hdr_valid (clcm , check_trl )) {
340
346
smc -> sk .sk_err = EPROTO ;
341
347
reason_code = - EPROTO ;
342
348
goto out ;
343
349
}
350
+ datlen -= len ;
351
+ while (datlen ) {
352
+ u8 tmp [SMC_CLC_RECV_BUF_LEN ];
353
+
354
+ vec .iov_base = & tmp ;
355
+ vec .iov_len = SMC_CLC_RECV_BUF_LEN ;
356
+ /* receive remaining proposal message */
357
+ recvlen = datlen > SMC_CLC_RECV_BUF_LEN ?
358
+ SMC_CLC_RECV_BUF_LEN : datlen ;
359
+ iov_iter_kvec (& msg .msg_iter , READ , & vec , 1 , recvlen );
360
+ len = sock_recvmsg (smc -> clcsock , & msg , krflags );
361
+ datlen -= len ;
362
+ }
344
363
if (clcm -> type == SMC_CLC_DECLINE ) {
345
364
struct smc_clc_msg_decline * dclc ;
346
365
0 commit comments