aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2009-08-25 17:03:52 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-10 13:08:02 -0400
commit8abbe3a42324264c9d5cc4e7c3d265b5be6d82d6 (patch)
tree72fa0c25fa4337ef0be788a76fdad37615fb7f4c /drivers/scsi/libfc
parent370c3bd05cf02afabea9cd3f2de66202d6b516dc (diff)
[SCSI] libfc: fix handling of incoming Discover Address (ADISC) requests
The local port facility has been replying to ADISC requests without looking to see if the remote port is logged in. This is incorrect. An ADISC request requires PLOGI first. It should be rejected if the sending remote port is not logged in. This is like other incoming requests that require login, all of which should be handled in the remote port module. Move the ADISC request handling from fc_lport.c to fc_rport.c. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r--drivers/scsi/libfc/fc_lport.c53
-rw-r--r--drivers/scsi/libfc/fc_rport.c48
2 files changed, 48 insertions, 53 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 3f2f72390145..bd2f77197447 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -452,56 +452,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
452} 452}
453 453
454/** 454/**
455 * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
456 * @lport: Fibre Channel local port recieving the ADISC
457 * @sp: current sequence in the ADISC exchange
458 * @fp: ADISC request frame
459 *
460 * Locking Note: The lport lock is expected to be held before calling
461 * this function.
462 */
463static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp,
464 struct fc_lport *lport)
465{
466 struct fc_frame *fp;
467 struct fc_exch *ep = fc_seq_exch(sp);
468 struct fc_els_adisc *req, *rp;
469 struct fc_seq_els_data rjt_data;
470 size_t len;
471 u32 f_ctl;
472
473 FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n",
474 fc_lport_state(lport));
475
476 req = fc_frame_payload_get(in_fp, sizeof(*req));
477 if (!req) {
478 rjt_data.fp = NULL;
479 rjt_data.reason = ELS_RJT_LOGIC;
480 rjt_data.explan = ELS_EXPL_NONE;
481 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
482 } else {
483 len = sizeof(*rp);
484 fp = fc_frame_alloc(lport, len);
485 if (fp) {
486 rp = fc_frame_payload_get(fp, len);
487 memset(rp, 0, len);
488 rp->adisc_cmd = ELS_LS_ACC;
489 rp->adisc_wwpn = htonll(lport->wwpn);
490 rp->adisc_wwnn = htonll(lport->wwnn);
491 hton24(rp->adisc_port_id,
492 fc_host_port_id(lport->host));
493 sp = lport->tt.seq_start_next(sp);
494 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
495 f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
496 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
497 FC_TYPE_ELS, f_ctl, 0);
498 lport->tt.seq_send(lport, sp, fp);
499 }
500 }
501 fc_frame_free(in_fp);
502}
503
504/**
505 * fc_lport_recv_logo_req() - Handle received fabric LOGO request 455 * fc_lport_recv_logo_req() - Handle received fabric LOGO request
506 * @lport: Fibre Channel local port recieving the LOGO 456 * @lport: Fibre Channel local port recieving the LOGO
507 * @sp: current sequence in the LOGO exchange 457 * @sp: current sequence in the LOGO exchange
@@ -849,9 +799,6 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
849 case ELS_RNID: 799 case ELS_RNID:
850 recv = fc_lport_recv_rnid_req; 800 recv = fc_lport_recv_rnid_req;
851 break; 801 break;
852 case ELS_ADISC:
853 recv = fc_lport_recv_adisc_req;
854 break;
855 } 802 }
856 803
857 recv(sp, fp, lport); 804 recv(sp, fp, lport);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index c33e25851082..03ea6748e7ee 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1012,6 +1012,50 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
1012} 1012}
1013 1013
1014/** 1014/**
1015 * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request
1016 * @rdata: remote port private
1017 * @sp: current sequence in the ADISC exchange
1018 * @in_fp: ADISC request frame
1019 *
1020 * Locking Note: Called with the lport and rport locks held.
1021 */
1022static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
1023 struct fc_seq *sp, struct fc_frame *in_fp)
1024{
1025 struct fc_lport *lport = rdata->local_port;
1026 struct fc_frame *fp;
1027 struct fc_exch *ep = fc_seq_exch(sp);
1028 struct fc_els_adisc *adisc;
1029 struct fc_seq_els_data rjt_data;
1030 u32 f_ctl;
1031
1032 FC_RPORT_DBG(rdata, "Received ADISC request\n");
1033
1034 adisc = fc_frame_payload_get(in_fp, sizeof(*adisc));
1035 if (!adisc) {
1036 rjt_data.fp = NULL;
1037 rjt_data.reason = ELS_RJT_PROT;
1038 rjt_data.explan = ELS_EXPL_INV_LEN;
1039 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
1040 goto drop;
1041 }
1042
1043 fp = fc_frame_alloc(lport, sizeof(*adisc));
1044 if (!fp)
1045 goto drop;
1046 fc_adisc_fill(lport, fp);
1047 adisc = fc_frame_payload_get(fp, sizeof(*adisc));
1048 adisc->adisc_cmd = ELS_LS_ACC;
1049 sp = lport->tt.seq_start_next(sp);
1050 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
1051 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
1052 FC_TYPE_ELS, f_ctl, 0);
1053 lport->tt.seq_send(lport, sp, fp);
1054drop:
1055 fc_frame_free(in_fp);
1056}
1057
1058/**
1015 * fc_rport_recv_els_req() - handle a validated ELS request. 1059 * fc_rport_recv_els_req() - handle a validated ELS request.
1016 * @lport: Fibre Channel local port 1060 * @lport: Fibre Channel local port
1017 * @sp: current sequence in the PLOGI exchange 1061 * @sp: current sequence in the PLOGI exchange
@@ -1062,6 +1106,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
1062 case ELS_PRLO: 1106 case ELS_PRLO:
1063 fc_rport_recv_prlo_req(rdata, sp, fp); 1107 fc_rport_recv_prlo_req(rdata, sp, fp);
1064 break; 1108 break;
1109 case ELS_ADISC:
1110 fc_rport_recv_adisc_req(rdata, sp, fp);
1111 break;
1065 case ELS_RRQ: 1112 case ELS_RRQ:
1066 els_data.fp = fp; 1113 els_data.fp = fp;
1067 lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); 1114 lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
@@ -1111,6 +1158,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
1111 break; 1158 break;
1112 case ELS_PRLI: 1159 case ELS_PRLI:
1113 case ELS_PRLO: 1160 case ELS_PRLO:
1161 case ELS_ADISC:
1114 case ELS_RRQ: 1162 case ELS_RRQ:
1115 case ELS_REC: 1163 case ELS_REC:
1116 fc_rport_recv_els_req(lport, sp, fp); 1164 fc_rport_recv_els_req(lport, sp, fp);