2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include <arpa/inet.h>
24 #include "iscsi-private.h"
26 int iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data)
28 struct iscsi_pdu *pdu;
33 printf("trying to login on NULL context\n");
37 if (iscsi->is_loggedin != 0) {
38 printf("trying to login while already logged in\n");
42 switch (iscsi->session_type) {
43 case ISCSI_SESSION_DISCOVERY:
44 case ISCSI_SESSION_NORMAL:
47 printf("trying to login without setting session type\n");
51 pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGIN_REQUEST, ISCSI_PDU_LOGIN_RESPONSE);
53 printf("Failed to allocate login pdu\n");
58 iscsi_pdu_set_immediate(pdu);
61 iscsi_pdu_set_pduflags(pdu, ISCSI_PDU_LOGIN_TRANSIT|ISCSI_PDU_LOGIN_CSG_OPNEG|ISCSI_PDU_LOGIN_NSG_FF);
65 if (asprintf(&str, "InitiatorName=%s", iscsi->initiator_name) == -1) {
66 printf("asprintf failed\n");
67 iscsi_free_pdu(iscsi, pdu);
70 ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
73 printf("pdu add data failed\n");
74 iscsi_free_pdu(iscsi, pdu);
80 if (asprintf(&str, "InitiatorAlias=%s", iscsi->alias) == -1) {
81 printf("asprintf failed\n");
82 iscsi_free_pdu(iscsi, pdu);
85 ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
88 printf("pdu add data failed\n");
89 iscsi_free_pdu(iscsi, pdu);
95 if (iscsi->session_type == ISCSI_SESSION_NORMAL) {
96 if (iscsi->target_name == NULL) {
97 printf("trying normal connect but target name not set\n");
98 iscsi_free_pdu(iscsi, pdu);
102 if (asprintf(&str, "TargetName=%s", iscsi->target_name) == -1) {
103 printf("asprintf failed\n");
104 iscsi_free_pdu(iscsi, pdu);
107 ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
110 printf("pdu add data failed\n");
111 iscsi_free_pdu(iscsi, pdu);
117 switch (iscsi->session_type) {
118 case ISCSI_SESSION_DISCOVERY:
119 str = "SessionType=Discovery";
121 case ISCSI_SESSION_NORMAL:
122 str = "SessionType=Normal";
125 printf("can not handle sessions %d yet\n", iscsi->session_type);
128 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
129 printf("pdu add data failed\n");
130 iscsi_free_pdu(iscsi, pdu);
134 str = "HeaderDigest=None";
135 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
136 printf("pdu add data failed\n");
137 iscsi_free_pdu(iscsi, pdu);
140 str = "DataDigest=None";
141 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
142 printf("pdu add data failed\n");
143 iscsi_free_pdu(iscsi, pdu);
146 str = "InitialR2T=Yes";
147 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
148 printf("pdu add data failed\n");
149 iscsi_free_pdu(iscsi, pdu);
152 str = "ImmediateData=Yes";
153 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
154 printf("pdu add data failed\n");
155 iscsi_free_pdu(iscsi, pdu);
158 str = "MaxBurstLength=262144";
159 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
160 printf("pdu add data failed\n");
161 iscsi_free_pdu(iscsi, pdu);
164 str = "FirstBurstLength=262144";
165 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
166 printf("pdu add data failed\n");
167 iscsi_free_pdu(iscsi, pdu);
170 str = "MaxRecvDataSegmentLength=262144";
171 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
172 printf("pdu add data failed\n");
173 iscsi_free_pdu(iscsi, pdu);
176 str = "DataPDUInOrder=Yes";
177 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
178 printf("pdu add data failed\n");
179 iscsi_free_pdu(iscsi, pdu);
182 str = "DataSequenceInOrder=Yes";
183 if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
184 printf("pdu add data failed\n");
185 iscsi_free_pdu(iscsi, pdu);
191 pdu->private_data = private_data;
193 if (iscsi_queue_pdu(iscsi, pdu) != 0) {
194 printf("failed to queue iscsi login pdu\n");
195 iscsi_free_pdu(iscsi, pdu);
202 int iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, const unsigned char *hdr, int size)
206 if (size < ISCSI_HEADER_SIZE) {
207 printf("dont have enough data to read status from login reply\n");
211 /* XXX here we should parse the data returned in case the target renegotiated some
213 * we should also do proper handshaking if the target is not yet prepared to transition
216 status = ntohs(*(uint16_t *)&hdr[36]);
218 pdu->callback(iscsi, ISCSI_STATUS_ERROR, NULL, pdu->private_data);
222 iscsi->statsn = ntohs(*(uint16_t *)&hdr[24]);
224 iscsi->is_loggedin = 1;
225 pdu->callback(iscsi, ISCSI_STATUS_GOOD, NULL, pdu->private_data);
231 int iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data)
233 struct iscsi_pdu *pdu;
236 printf("trying to logout on NULL context\n");
240 if (iscsi->is_loggedin == 0) {
241 printf("trying to logout while not logged in\n");
245 pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGOUT_REQUEST, ISCSI_PDU_LOGOUT_RESPONSE);
247 printf("Failed to allocate logout pdu\n");
251 /* logout request has the immediate flag set */
252 iscsi_pdu_set_immediate(pdu);
254 /* flags : close the session */
255 iscsi_pdu_set_pduflags(pdu, 0x80);
259 pdu->private_data = private_data;
261 if (iscsi_queue_pdu(iscsi, pdu) != 0) {
262 printf("failed to queue iscsi logout pdu\n");
263 iscsi_free_pdu(iscsi, pdu);
270 int iscsi_process_logout_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, const unsigned char *hdr, int size _U_)
272 iscsi->is_loggedin = 0;
273 pdu->callback(iscsi, ISCSI_STATUS_GOOD, NULL, pdu->private_data);
278 int iscsi_set_session_type(struct iscsi_context *iscsi, enum iscsi_session_type session_type)
281 printf("Trying to set sesssion type on NULL context\n");
284 if (iscsi->is_loggedin) {
285 printf("trying to set session type while logged in\n");
289 iscsi->session_type = session_type;