summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMark Rustad <mark.d.rustad@intel.com>2013-05-18 06:01:36 +0200
committerRobert Love <robert.w.love@intel.com>2013-07-09 18:29:14 +0200
commite0335f67a281cb8eb11868e614ee9390fbbe9b1d (patch)
treeff3fd672241c138b686bd155917ff21c49f6f60d /drivers/scsi
parentLinux 3.10 (diff)
downloadlinux-e0335f67a281cb8eb11868e614ee9390fbbe9b1d.tar.xz
linux-e0335f67a281cb8eb11868e614ee9390fbbe9b1d.zip
libfc: Reject PLOGI from nodes with incompatible role
Reject a PLOGI from a node with an incompatible role, that is, initiator-to-initiator or target-to-target. Signed-off-by: Mark Rustad <mark.d.rustad@intel.com> Reviewed-by: Yi Zou <yi.zou@intel.com> Tested-by: Jack Morgan <jack.morgan@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libfc/fc_rport.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 6bbb9447b75d..c710d908fda6 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -926,6 +926,20 @@ err:
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
}
+static bool
+fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata)
+{
+ if (rdata->ids.roles == FC_PORT_ROLE_UNKNOWN)
+ return true;
+ if ((rdata->ids.roles & FC_PORT_ROLE_FCP_TARGET) &&
+ (lport->service_params & FCP_SPPF_INIT_FCN))
+ return true;
+ if ((rdata->ids.roles & FC_PORT_ROLE_FCP_INITIATOR) &&
+ (lport->service_params & FCP_SPPF_TARG_FCN))
+ return true;
+ return false;
+}
+
/**
* fc_rport_enter_plogi() - Send Port Login (PLOGI) request
* @rdata: The remote port to send a PLOGI to
@@ -938,6 +952,12 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
struct fc_lport *lport = rdata->local_port;
struct fc_frame *fp;
+ if (!fc_rport_compatible_roles(lport, rdata)) {
+ FC_RPORT_DBG(rdata, "PLOGI suppressed for incompatible role\n");
+ fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
+ return;
+ }
+
FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",
fc_rport_state(rdata));
@@ -1646,6 +1666,13 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
rjt_data.explan = ELS_EXPL_NONE;
goto reject;
}
+ if (!fc_rport_compatible_roles(lport, rdata)) {
+ FC_RPORT_DBG(rdata, "Received PLOGI for incompatible role\n");
+ mutex_unlock(&rdata->rp_mutex);
+ rjt_data.reason = ELS_RJT_LOGIC;
+ rjt_data.explan = ELS_EXPL_NONE;
+ goto reject;
+ }
/*
* Get session payload size from incoming PLOGI.