Skip to content

Commit fb4f792

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: tolerate future SMCD versions
CLC proposal messages of future SMCD versions could be larger than SMCD V1 CLC proposal messages. To enable toleration in SMC V1 the receival of CLC proposal messages is adapted: * accept larger length values in CLC proposal * check trailing eye catcher for incoming CLC proposal with V1 length only * receive the whole CLC proposal even in cases it does not fit into the V1 buffer Fixes: e7b7a64 ("smc: support variable CLC proposal messages") Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: Karsten Graul <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 82087c0 commit fb4f792

File tree

2 files changed

+34
-13
lines changed

2 files changed

+34
-13
lines changed

net/smc/smc_clc.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
2929
#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
30+
#define SMC_CLC_RECV_BUF_LEN 100
3031

3132
/* eye catcher "SMCR" EBCDIC for CLC messages */
3233
static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
@@ -36,7 +37,7 @@ static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
3637
/* check if received message has a correct header length and contains valid
3738
* heading and trailing eyecatchers
3839
*/
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)
4041
{
4142
struct smc_clc_msg_proposal_prefix *pclc_prfx;
4243
struct smc_clc_msg_accept_confirm *clc;
@@ -49,12 +50,9 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
4950
return false;
5051
switch (clcm->type) {
5152
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;
5553
pclc = (struct smc_clc_msg_proposal *)clcm;
5654
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
57-
if (ntohs(pclc->hdr.length) !=
55+
if (ntohs(pclc->hdr.length) <
5856
sizeof(*pclc) + ntohs(pclc->iparea_offset) +
5957
sizeof(*pclc_prfx) +
6058
pclc_prfx->ipv6_prefixes_cnt *
@@ -86,7 +84,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
8684
default:
8785
return false;
8886
}
89-
if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
87+
if (check_trl &&
88+
memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
9089
memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
9190
return false;
9291
return true;
@@ -276,7 +275,8 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
276275
struct msghdr msg = {NULL, 0};
277276
int reason_code = 0;
278277
struct kvec vec = {buf, buflen};
279-
int len, datlen;
278+
int len, datlen, recvlen;
279+
bool check_trl = true;
280280
int krflags;
281281

282282
/* 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,
320320
}
321321
datlen = ntohs(clcm->length);
322322
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) ||
327324
((clcm->type != SMC_CLC_DECLINE) &&
328325
(clcm->type != expected_type))) {
329326
smc->sk.sk_err = EPROTO;
330327
reason_code = -EPROTO;
331328
goto out;
332329
}
333330

331+
if (clcm->type == SMC_CLC_PROPOSAL && clcm->path == SMC_TYPE_N)
332+
reason_code = SMC_CLC_DECL_VERSMISMAT; /* just V2 offered */
333+
334334
/* receive the complete CLC message */
335335
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);
337343
krflags = MSG_WAITALL;
338344
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)) {
340346
smc->sk.sk_err = EPROTO;
341347
reason_code = -EPROTO;
342348
goto out;
343349
}
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+
}
344363
if (clcm->type == SMC_CLC_DECLINE) {
345364
struct smc_clc_msg_decline *dclc;
346365

net/smc/smc_clc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define SMC_CLC_V1 0x1 /* SMC version */
2626
#define SMC_TYPE_R 0 /* SMC-R only */
2727
#define SMC_TYPE_D 1 /* SMC-D only */
28+
#define SMC_TYPE_N 2 /* neither SMC-R nor SMC-D */
2829
#define SMC_TYPE_B 3 /* SMC-R and SMC-D */
2930
#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
3031
#define CLC_WAIT_TIME_SHORT HZ /* short wait time on clcsock */
@@ -46,6 +47,7 @@
4647
#define SMC_CLC_DECL_ISMVLANERR 0x03090000 /* err to reg vlan id on ism dev */
4748
#define SMC_CLC_DECL_NOACTLINK 0x030a0000 /* no active smc-r link in lgr */
4849
#define SMC_CLC_DECL_NOSRVLINK 0x030b0000 /* SMC-R link from srv not found */
50+
#define SMC_CLC_DECL_VERSMISMAT 0x030c0000 /* SMC version mismatch */
4951
#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
5052
#define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
5153
#define SMC_CLC_DECL_INTERR 0x09990000 /* internal error */

0 commit comments

Comments
 (0)