Commit a2f6a024 authored by Joe Eykholt's avatar Joe Eykholt Committed by James Bottomley

[SCSI] libfc: recode incoming PRLI handling

Reduce indentation in fc_rport_recv_prli_req() using gotos.
Also add payload length checks.
Signed-off-by: default avatarJoe Eykholt <jeykholt@cisco.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent fc193172
...@@ -1442,59 +1442,39 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1442,59 +1442,39 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
struct fc_els_spp *spp; /* response spp */ struct fc_els_spp *spp; /* response spp */
unsigned int len; unsigned int len;
unsigned int plen; unsigned int plen;
enum fc_els_rjt_reason reason = ELS_RJT_UNAB;
enum fc_els_rjt_explan explan = ELS_EXPL_NONE;
enum fc_els_spp_resp resp; enum fc_els_spp_resp resp;
struct fc_seq_els_data rjt_data; struct fc_seq_els_data rjt_data;
u32 f_ctl; u32 f_ctl;
u32 fcp_parm; u32 fcp_parm;
u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 roles = FC_RPORT_ROLE_UNKNOWN;
rjt_data.fp = NULL;
rjt_data.fp = NULL;
fh = fc_frame_header_get(rx_fp); fh = fc_frame_header_get(rx_fp);
FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
fc_rport_state(rdata)); fc_rport_state(rdata));
switch (rdata->rp_state) {
case RPORT_ST_PRLI:
case RPORT_ST_RTV:
case RPORT_ST_READY:
case RPORT_ST_ADISC:
reason = ELS_RJT_NONE;
break;
default:
fc_frame_free(rx_fp);
return;
break;
}
len = fr_len(rx_fp) - sizeof(*fh); len = fr_len(rx_fp) - sizeof(*fh);
pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); pp = fc_frame_payload_get(rx_fp, sizeof(*pp));
if (pp == NULL) { if (!pp)
reason = ELS_RJT_PROT; goto reject_len;
explan = ELS_EXPL_INV_LEN;
} else {
plen = ntohs(pp->prli.prli_len); plen = ntohs(pp->prli.prli_len);
if ((plen % 4) != 0 || plen > len) { if ((plen % 4) != 0 || plen > len || plen < 16)
reason = ELS_RJT_PROT; goto reject_len;
explan = ELS_EXPL_INV_LEN; if (plen < len)
} else if (plen < len) {
len = plen; len = plen;
}
plen = pp->prli.prli_spp_len; plen = pp->prli.prli_spp_len;
if ((plen % 4) != 0 || plen < sizeof(*spp) || if ((plen % 4) != 0 || plen < sizeof(*spp) ||
plen > len || len < sizeof(*pp)) { plen > len || len < sizeof(*pp) || plen < 12)
reason = ELS_RJT_PROT; goto reject_len;
explan = ELS_EXPL_INV_LEN;
}
rspp = &pp->spp; rspp = &pp->spp;
fp = fc_frame_alloc(lport, len);
if (!fp) {
rjt_data.reason = ELS_RJT_UNAB;
rjt_data.explan = ELS_EXPL_INSUF_RES;
goto reject;
} }
if (reason != ELS_RJT_NONE ||
(fp = fc_frame_alloc(lport, len)) == NULL) {
rjt_data.reason = reason;
rjt_data.explan = explan;
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
} else {
sp = lport->tt.seq_start_next(sp); sp = lport->tt.seq_start_next(sp);
WARN_ON(!sp); WARN_ON(!sp);
pp = fc_frame_payload_get(fp, len); pp = fc_frame_payload_get(fp, len);
...@@ -1519,8 +1499,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1519,8 +1499,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
spp->spp_type_ext = rspp->spp_type_ext; spp->spp_type_ext = rspp->spp_type_ext;
spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
resp = FC_SPP_RESP_ACK; resp = FC_SPP_RESP_ACK;
if (rspp->spp_flags & FC_SPP_RPA_VAL)
resp = FC_SPP_RESP_NO_PA;
switch (rspp->spp_type) { switch (rspp->spp_type) {
case 0: /* common to all FC-4 types */ case 0: /* common to all FC-4 types */
break; break;
...@@ -1535,8 +1514,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1535,8 +1514,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
roles |= FC_RPORT_ROLE_FCP_TARGET; roles |= FC_RPORT_ROLE_FCP_TARGET;
rdata->ids.roles = roles; rdata->ids.roles = roles;
spp->spp_params = spp->spp_params = htonl(lport->service_params);
htonl(lport->service_params);
break; break;
default: default:
resp = FC_SPP_RESP_INVL; resp = FC_SPP_RESP_INVL;
...@@ -1558,20 +1536,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1558,20 +1536,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
FC_TYPE_ELS, f_ctl, 0); FC_TYPE_ELS, f_ctl, 0);
lport->tt.seq_send(lport, sp, fp); lport->tt.seq_send(lport, sp, fp);
/*
* Get lock and re-check state.
*/
switch (rdata->rp_state) { switch (rdata->rp_state) {
case RPORT_ST_PRLI: case RPORT_ST_PRLI:
fc_rport_enter_ready(rdata); fc_rport_enter_ready(rdata);
break; break;
case RPORT_ST_READY:
case RPORT_ST_ADISC:
break;
default: default:
break; break;
} }
} goto drop;
reject_len:
rjt_data.reason = ELS_RJT_PROT;
rjt_data.explan = ELS_EXPL_INV_LEN;
reject:
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
drop:
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment