Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+87 −108
Original line number Diff line number Diff line
@@ -1442,59 +1442,39 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
	struct fc_els_spp *spp;	/* response spp */
	unsigned int len;
	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;
	struct fc_seq_els_data rjt_data;
	u32 f_ctl;
	u32 fcp_parm;
	u32 roles = FC_RPORT_ROLE_UNKNOWN;
	rjt_data.fp = NULL;

	rjt_data.fp = NULL;
	fh = fc_frame_header_get(rx_fp);

	FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
		     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);
	pp = fc_frame_payload_get(rx_fp, sizeof(*pp));
	if (pp == NULL) {
		reason = ELS_RJT_PROT;
		explan = ELS_EXPL_INV_LEN;
	} else {
	if (!pp)
		goto reject_len;
	plen = ntohs(pp->prli.prli_len);
		if ((plen % 4) != 0 || plen > len) {
			reason = ELS_RJT_PROT;
			explan = ELS_EXPL_INV_LEN;
		} else if (plen < len) {
	if ((plen % 4) != 0 || plen > len || plen < 16)
		goto reject_len;
	if (plen < len)
		len = plen;
		}
	plen = pp->prli.prli_spp_len;
	if ((plen % 4) != 0 || plen < sizeof(*spp) ||
		    plen > len || len < sizeof(*pp)) {
			reason = ELS_RJT_PROT;
			explan = ELS_EXPL_INV_LEN;
		}
	    plen > len || len < sizeof(*pp) || plen < 12)
		goto reject_len;
	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);
	WARN_ON(!sp);
	pp = fc_frame_payload_get(fp, len);
@@ -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_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
		resp = FC_SPP_RESP_ACK;
			if (rspp->spp_flags & FC_SPP_RPA_VAL)
				resp = FC_SPP_RESP_NO_PA;

		switch (rspp->spp_type) {
		case 0:	/* common to all FC-4 types */
			break;
@@ -1535,8 +1514,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
				roles |= FC_RPORT_ROLE_FCP_TARGET;
			rdata->ids.roles = roles;

				spp->spp_params =
					htonl(lport->service_params);
			spp->spp_params = htonl(lport->service_params);
			break;
		default:
			resp = FC_SPP_RESP_INVL;
@@ -1558,20 +1536,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
		       FC_TYPE_ELS, f_ctl, 0);
	lport->tt.seq_send(lport, sp, fp);

		/*
		 * Get lock and re-check state.
		 */
	switch (rdata->rp_state) {
	case RPORT_ST_PRLI:
		fc_rport_enter_ready(rdata);
		break;
		case RPORT_ST_READY:
		case RPORT_ST_ADISC:
			break;
	default:
		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);
}