You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

iscsi.c 55KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25. #include <byteswap.h>
  26. #include <ipxe/vsprintf.h>
  27. #include <ipxe/socket.h>
  28. #include <ipxe/xfer.h>
  29. #include <ipxe/open.h>
  30. #include <ipxe/scsi.h>
  31. #include <ipxe/process.h>
  32. #include <ipxe/uaccess.h>
  33. #include <ipxe/tcpip.h>
  34. #include <ipxe/settings.h>
  35. #include <ipxe/features.h>
  36. #include <ipxe/base16.h>
  37. #include <ipxe/base64.h>
  38. #include <ipxe/iscsi.h>
  39. /** @file
  40. *
  41. * iSCSI protocol
  42. *
  43. */
  44. FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
  45. /* Disambiguate the various error causes */
  46. #define EACCES_INCORRECT_TARGET_USERNAME \
  47. __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
  48. #define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
  49. __einfo_uniqify ( EINFO_EACCES, 0x01, "Incorrect target username" )
  50. #define EACCES_INCORRECT_TARGET_PASSWORD \
  51. __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_PASSWORD )
  52. #define EINFO_EACCES_INCORRECT_TARGET_PASSWORD \
  53. __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect target password" )
  54. #define ENOTSUP_INITIATOR_STATUS \
  55. __einfo_error ( EINFO_ENOTSUP_INITIATOR_STATUS )
  56. #define EINFO_ENOTSUP_INITIATOR_STATUS \
  57. __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported initiator status" )
  58. #define ENOTSUP_OPCODE \
  59. __einfo_error ( EINFO_ENOTSUP_OPCODE )
  60. #define EINFO_ENOTSUP_OPCODE \
  61. __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported opcode" )
  62. #define ENOTSUP_DISCOVERY \
  63. __einfo_error ( EINFO_ENOTSUP_DISCOVERY )
  64. #define EINFO_ENOTSUP_DISCOVERY \
  65. __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Discovery not supported" )
  66. #define EPERM_INITIATOR_AUTHENTICATION \
  67. __einfo_error ( EINFO_EPERM_INITIATOR_AUTHENTICATION )
  68. #define EINFO_EPERM_INITIATOR_AUTHENTICATION \
  69. __einfo_uniqify ( EINFO_EPERM, 0x01, "Initiator authentication failed" )
  70. #define EPERM_INITIATOR_AUTHORISATION \
  71. __einfo_error ( EINFO_EPERM_INITIATOR_AUTHORISATION )
  72. #define EINFO_EPERM_INITIATOR_AUTHORISATION \
  73. __einfo_uniqify ( EINFO_EPERM, 0x02, "Initiator not authorised" )
  74. #define EPROTO_INVALID_CHAP_ALGORITHM \
  75. __einfo_error ( EINFO_EPROTO_INVALID_CHAP_ALGORITHM )
  76. #define EINFO_EPROTO_INVALID_CHAP_ALGORITHM \
  77. __einfo_uniqify ( EINFO_EPROTO, 0x01, "Invalid CHAP algorithm" )
  78. #define EPROTO_INVALID_CHAP_IDENTIFIER \
  79. __einfo_error ( EINFO_EPROTO_INVALID_CHAP_IDENTIFIER )
  80. #define EINFO_EPROTO_INVALID_CHAP_IDENTIFIER \
  81. __einfo_uniqify ( EINFO_EPROTO, 0x02, "Invalid CHAP identifier" )
  82. #define EPROTO_INVALID_LARGE_BINARY \
  83. __einfo_error ( EINFO_EPROTO_INVALID_LARGE_BINARY )
  84. #define EINFO_EPROTO_INVALID_LARGE_BINARY \
  85. __einfo_uniqify ( EINFO_EPROTO, 0x03, "Invalid large binary" )
  86. #define EPROTO_INVALID_CHAP_RESPONSE \
  87. __einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
  88. #define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
  89. __einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
  90. /** iSCSI initiator name (explicitly specified) */
  91. static char *iscsi_explicit_initiator_iqn;
  92. /** Default iSCSI initiator name (constructed from hostname) */
  93. static char *iscsi_default_initiator_iqn;
  94. /** iSCSI initiator username */
  95. static char *iscsi_initiator_username;
  96. /** iSCSI initiator password */
  97. static char *iscsi_initiator_password;
  98. /** iSCSI target username */
  99. static char *iscsi_target_username;
  100. /** iSCSI target password */
  101. static char *iscsi_target_password;
  102. static void iscsi_start_tx ( struct iscsi_session *iscsi );
  103. static void iscsi_start_login ( struct iscsi_session *iscsi );
  104. static void iscsi_start_data_out ( struct iscsi_session *iscsi,
  105. unsigned int datasn );
  106. /**
  107. * Finish receiving PDU data into buffer
  108. *
  109. * @v iscsi iSCSI session
  110. */
  111. static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
  112. free ( iscsi->rx_buffer );
  113. iscsi->rx_buffer = NULL;
  114. }
  115. /**
  116. * Free iSCSI session
  117. *
  118. * @v refcnt Reference counter
  119. */
  120. static void iscsi_free ( struct refcnt *refcnt ) {
  121. struct iscsi_session *iscsi =
  122. container_of ( refcnt, struct iscsi_session, refcnt );
  123. free ( iscsi->target_address );
  124. free ( iscsi->target_iqn );
  125. free ( iscsi->initiator_username );
  126. free ( iscsi->initiator_password );
  127. free ( iscsi->target_username );
  128. free ( iscsi->target_password );
  129. chap_finish ( &iscsi->chap );
  130. iscsi_rx_buffered_data_done ( iscsi );
  131. free ( iscsi );
  132. }
  133. /**
  134. * Open iSCSI transport-layer connection
  135. *
  136. * @v iscsi iSCSI session
  137. * @ret rc Return status code
  138. */
  139. static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
  140. struct sockaddr_tcpip target;
  141. int rc;
  142. assert ( iscsi->tx_state == ISCSI_TX_IDLE );
  143. assert ( iscsi->rx_state == ISCSI_RX_BHS );
  144. assert ( iscsi->rx_offset == 0 );
  145. /* Open socket */
  146. memset ( &target, 0, sizeof ( target ) );
  147. target.st_port = htons ( iscsi->target_port );
  148. if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
  149. ( struct sockaddr * ) &target,
  150. iscsi->target_address,
  151. NULL ) ) != 0 ) {
  152. DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
  153. iscsi, strerror ( rc ) );
  154. return rc;
  155. }
  156. /* Enter security negotiation phase */
  157. iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
  158. ISCSI_STATUS_STRINGS_SECURITY );
  159. if ( iscsi->target_username )
  160. iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
  161. /* Assign fresh initiator task tag */
  162. iscsi->itt++;
  163. /* Initiate login */
  164. iscsi_start_login ( iscsi );
  165. return 0;
  166. }
  167. /**
  168. * Close iSCSI transport-layer connection
  169. *
  170. * @v iscsi iSCSI session
  171. * @v rc Reason for close
  172. *
  173. * Closes the transport-layer connection and resets the session state
  174. * ready to attempt a fresh login.
  175. */
  176. static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
  177. /* Close all data transfer interfaces */
  178. xfer_close ( &iscsi->socket, rc );
  179. /* Clear connection status */
  180. iscsi->status = 0;
  181. /* Reset TX and RX state machines */
  182. iscsi->tx_state = ISCSI_TX_IDLE;
  183. iscsi->rx_state = ISCSI_RX_BHS;
  184. iscsi->rx_offset = 0;
  185. /* Free any temporary dynamically allocated memory */
  186. chap_finish ( &iscsi->chap );
  187. iscsi_rx_buffered_data_done ( iscsi );
  188. }
  189. /**
  190. * Mark iSCSI SCSI operation as complete
  191. *
  192. * @v iscsi iSCSI session
  193. * @v rc Return status code
  194. *
  195. * Note that iscsi_scsi_done() will not close the connection, and must
  196. * therefore be called only when the internal state machines are in an
  197. * appropriate state, otherwise bad things may happen on the next call
  198. * to iscsi_issue(). The general rule is to call iscsi_scsi_done()
  199. * only at the end of receiving a PDU; at this point the TX and RX
  200. * engines should both be idle.
  201. */
  202. static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
  203. assert ( iscsi->tx_state == ISCSI_TX_IDLE );
  204. assert ( iscsi->command != NULL );
  205. iscsi->command->rc = rc;
  206. iscsi->command = NULL;
  207. }
  208. /****************************************************************************
  209. *
  210. * iSCSI SCSI command issuing
  211. *
  212. */
  213. /**
  214. * Build iSCSI SCSI command BHS
  215. *
  216. * @v iscsi iSCSI session
  217. *
  218. * We don't currently support bidirectional commands (i.e. with both
  219. * Data-In and Data-Out segments); these would require providing code
  220. * to generate an AHS, and there doesn't seem to be any need for it at
  221. * the moment.
  222. */
  223. static void iscsi_start_command ( struct iscsi_session *iscsi ) {
  224. struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
  225. assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
  226. /* Construct BHS and initiate transmission */
  227. iscsi_start_tx ( iscsi );
  228. command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
  229. command->flags = ( ISCSI_FLAG_FINAL |
  230. ISCSI_COMMAND_ATTR_SIMPLE );
  231. if ( iscsi->command->data_in )
  232. command->flags |= ISCSI_COMMAND_FLAG_READ;
  233. if ( iscsi->command->data_out )
  234. command->flags |= ISCSI_COMMAND_FLAG_WRITE;
  235. /* lengths left as zero */
  236. command->lun = iscsi->lun;
  237. command->itt = htonl ( ++iscsi->itt );
  238. command->exp_len = htonl ( iscsi->command->data_in_len |
  239. iscsi->command->data_out_len );
  240. command->cmdsn = htonl ( iscsi->cmdsn );
  241. command->expstatsn = htonl ( iscsi->statsn + 1 );
  242. memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
  243. DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
  244. iscsi, SCSI_CDB_DATA ( command->cdb ),
  245. ( iscsi->command->data_in ? "in" : "out" ),
  246. ( iscsi->command->data_in ?
  247. iscsi->command->data_in_len :
  248. iscsi->command->data_out_len ) );
  249. }
  250. /**
  251. * Receive data segment of an iSCSI SCSI response PDU
  252. *
  253. * @v iscsi iSCSI session
  254. * @v data Received data
  255. * @v len Length of received data
  256. * @v remaining Data remaining after this data
  257. * @ret rc Return status code
  258. */
  259. static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
  260. const void *data, size_t len,
  261. size_t remaining ) {
  262. struct iscsi_bhs_scsi_response *response
  263. = &iscsi->rx_bhs.scsi_response;
  264. int sense_offset;
  265. /* Capture the sense response code as it floats past, if present */
  266. sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
  267. if ( ( sense_offset >= 0 ) && len ) {
  268. iscsi->command->sense_response =
  269. * ( ( char * ) data + sense_offset );
  270. }
  271. /* Wait for whole SCSI response to arrive */
  272. if ( remaining )
  273. return 0;
  274. /* Record SCSI status code */
  275. iscsi->command->status = response->status;
  276. /* Check for errors */
  277. if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
  278. return -EIO;
  279. /* Mark as completed */
  280. iscsi_scsi_done ( iscsi, 0 );
  281. return 0;
  282. }
  283. /**
  284. * Receive data segment of an iSCSI data-in PDU
  285. *
  286. * @v iscsi iSCSI session
  287. * @v data Received data
  288. * @v len Length of received data
  289. * @v remaining Data remaining after this data
  290. * @ret rc Return status code
  291. */
  292. static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
  293. const void *data, size_t len,
  294. size_t remaining ) {
  295. struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
  296. unsigned long offset;
  297. /* Copy data to data-in buffer */
  298. offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
  299. assert ( iscsi->command != NULL );
  300. assert ( iscsi->command->data_in );
  301. assert ( ( offset + len ) <= iscsi->command->data_in_len );
  302. copy_to_user ( iscsi->command->data_in, offset, data, len );
  303. /* Wait for whole SCSI response to arrive */
  304. if ( remaining )
  305. return 0;
  306. /* Mark as completed if status is present */
  307. if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
  308. assert ( ( offset + len ) == iscsi->command->data_in_len );
  309. assert ( data_in->flags & ISCSI_FLAG_FINAL );
  310. iscsi->command->status = data_in->status;
  311. /* iSCSI cannot return an error status via a data-in */
  312. iscsi_scsi_done ( iscsi, 0 );
  313. }
  314. return 0;
  315. }
  316. /**
  317. * Receive data segment of an iSCSI R2T PDU
  318. *
  319. * @v iscsi iSCSI session
  320. * @v data Received data
  321. * @v len Length of received data
  322. * @v remaining Data remaining after this data
  323. * @ret rc Return status code
  324. */
  325. static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
  326. const void *data __unused, size_t len __unused,
  327. size_t remaining __unused ) {
  328. struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
  329. /* Record transfer parameters and trigger first data-out */
  330. iscsi->ttt = ntohl ( r2t->ttt );
  331. iscsi->transfer_offset = ntohl ( r2t->offset );
  332. iscsi->transfer_len = ntohl ( r2t->len );
  333. iscsi_start_data_out ( iscsi, 0 );
  334. return 0;
  335. }
  336. /**
  337. * Build iSCSI data-out BHS
  338. *
  339. * @v iscsi iSCSI session
  340. * @v datasn Data sequence number within the transfer
  341. *
  342. */
  343. static void iscsi_start_data_out ( struct iscsi_session *iscsi,
  344. unsigned int datasn ) {
  345. struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
  346. unsigned long offset;
  347. unsigned long remaining;
  348. unsigned long len;
  349. /* We always send 512-byte Data-Out PDUs; this removes the
  350. * need to worry about the target's MaxRecvDataSegmentLength.
  351. */
  352. offset = datasn * 512;
  353. remaining = iscsi->transfer_len - offset;
  354. len = remaining;
  355. if ( len > 512 )
  356. len = 512;
  357. /* Construct BHS and initiate transmission */
  358. iscsi_start_tx ( iscsi );
  359. data_out->opcode = ISCSI_OPCODE_DATA_OUT;
  360. if ( len == remaining )
  361. data_out->flags = ( ISCSI_FLAG_FINAL );
  362. ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
  363. data_out->lun = iscsi->lun;
  364. data_out->itt = htonl ( iscsi->itt );
  365. data_out->ttt = htonl ( iscsi->ttt );
  366. data_out->expstatsn = htonl ( iscsi->statsn + 1 );
  367. data_out->datasn = htonl ( datasn );
  368. data_out->offset = htonl ( iscsi->transfer_offset + offset );
  369. DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
  370. iscsi, datasn, len );
  371. }
  372. /**
  373. * Complete iSCSI data-out PDU transmission
  374. *
  375. * @v iscsi iSCSI session
  376. *
  377. */
  378. static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
  379. struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
  380. /* If we haven't reached the end of the sequence, start
  381. * sending the next data-out PDU.
  382. */
  383. if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
  384. iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
  385. }
  386. /**
  387. * Send iSCSI data-out data segment
  388. *
  389. * @v iscsi iSCSI session
  390. * @ret rc Return status code
  391. */
  392. static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
  393. struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
  394. struct io_buffer *iobuf;
  395. unsigned long offset;
  396. size_t len;
  397. offset = ntohl ( data_out->offset );
  398. len = ISCSI_DATA_LEN ( data_out->lengths );
  399. assert ( iscsi->command != NULL );
  400. assert ( iscsi->command->data_out );
  401. assert ( ( offset + len ) <= iscsi->command->data_out_len );
  402. iobuf = xfer_alloc_iob ( &iscsi->socket, len );
  403. if ( ! iobuf )
  404. return -ENOMEM;
  405. copy_from_user ( iob_put ( iobuf, len ),
  406. iscsi->command->data_out, offset, len );
  407. return xfer_deliver_iob ( &iscsi->socket, iobuf );
  408. }
  409. /****************************************************************************
  410. *
  411. * iSCSI login
  412. *
  413. */
  414. /**
  415. * Build iSCSI login request strings
  416. *
  417. * @v iscsi iSCSI session
  418. *
  419. * These are the initial set of strings sent in the first login
  420. * request PDU. We want the following settings:
  421. *
  422. * HeaderDigest=None
  423. * DataDigest=None
  424. * MaxConnections is irrelevant; we make only one connection anyway [4]
  425. * InitialR2T=Yes [1]
  426. * ImmediateData is irrelevant; we never send immediate data [4]
  427. * MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
  428. * MaxBurstLength=262144 (default; we don't care) [3]
  429. * FirstBurstLength=262144 (default; we don't care)
  430. * DefaultTime2Wait=0 [2]
  431. * DefaultTime2Retain=0 [2]
  432. * MaxOutstandingR2T=1
  433. * DataPDUInOrder=Yes
  434. * DataSequenceInOrder=Yes
  435. * ErrorRecoveryLevel=0
  436. *
  437. * [1] InitialR2T has an OR resolution function, so the target may
  438. * force us to use it. We therefore simplify our logic by always
  439. * using it.
  440. *
  441. * [2] These ensure that we can safely start a new task once we have
  442. * reconnected after a failure, without having to manually tidy up
  443. * after the old one.
  444. *
  445. * [3] We are quite happy to use the RFC-defined default values for
  446. * these parameters, but some targets (notably OpenSolaris)
  447. * incorrectly assume a default value of zero, so we explicitly
  448. * specify the default values.
  449. *
  450. * [4] We are quite happy to use the RFC-defined default values for
  451. * these parameters, but some targets (notably a QNAP TS-639Pro) fail
  452. * unless they are supplied, so we explicitly specify the default
  453. * values.
  454. */
  455. static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
  456. void *data, size_t len ) {
  457. unsigned int used = 0;
  458. const char *auth_method;
  459. if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
  460. /* Default to allowing no authentication */
  461. auth_method = "None";
  462. /* If we have a credential to supply, permit CHAP */
  463. if ( iscsi->initiator_username )
  464. auth_method = "CHAP,None";
  465. /* If we have a credential to check, force CHAP */
  466. if ( iscsi->target_username )
  467. auth_method = "CHAP";
  468. used += ssnprintf ( data + used, len - used,
  469. "InitiatorName=%s%c"
  470. "TargetName=%s%c"
  471. "SessionType=Normal%c"
  472. "AuthMethod=%s%c",
  473. iscsi_initiator_iqn(), 0,
  474. iscsi->target_iqn, 0, 0,
  475. auth_method, 0 );
  476. }
  477. if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
  478. used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
  479. }
  480. if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
  481. char buf[ base16_encoded_len ( iscsi->chap.response_len ) + 1 ];
  482. assert ( iscsi->initiator_username != NULL );
  483. base16_encode ( iscsi->chap.response, iscsi->chap.response_len,
  484. buf );
  485. used += ssnprintf ( data + used, len - used,
  486. "CHAP_N=%s%cCHAP_R=0x%s%c",
  487. iscsi->initiator_username, 0, buf, 0 );
  488. }
  489. if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
  490. size_t challenge_len = ( sizeof ( iscsi->chap_challenge ) - 1 );
  491. char buf[ base16_encoded_len ( challenge_len ) + 1 ];
  492. base16_encode ( ( iscsi->chap_challenge + 1 ), challenge_len,
  493. buf );
  494. used += ssnprintf ( data + used, len - used,
  495. "CHAP_I=%d%cCHAP_C=0x%s%c",
  496. iscsi->chap_challenge[0], 0, buf, 0 );
  497. }
  498. if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
  499. used += ssnprintf ( data + used, len - used,
  500. "HeaderDigest=None%c"
  501. "DataDigest=None%c"
  502. "MaxConnections=1%c"
  503. "InitialR2T=Yes%c"
  504. "ImmediateData=No%c"
  505. "MaxRecvDataSegmentLength=8192%c"
  506. "MaxBurstLength=262144%c"
  507. "DefaultTime2Wait=0%c"
  508. "DefaultTime2Retain=0%c"
  509. "MaxOutstandingR2T=1%c"
  510. "DataPDUInOrder=Yes%c"
  511. "DataSequenceInOrder=Yes%c"
  512. "ErrorRecoveryLevel=0%c",
  513. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
  514. }
  515. return used;
  516. }
  517. /**
  518. * Build iSCSI login request BHS
  519. *
  520. * @v iscsi iSCSI session
  521. */
  522. static void iscsi_start_login ( struct iscsi_session *iscsi ) {
  523. struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
  524. int len;
  525. /* Construct BHS and initiate transmission */
  526. iscsi_start_tx ( iscsi );
  527. request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
  528. ISCSI_FLAG_IMMEDIATE );
  529. request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
  530. ISCSI_LOGIN_FLAG_TRANSITION );
  531. /* version_max and version_min left as zero */
  532. len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
  533. ISCSI_SET_LENGTHS ( request->lengths, 0, len );
  534. request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
  535. IANA_EN_FEN_SYSTEMS );
  536. /* isid_iana_qual left as zero */
  537. request->tsih = htons ( iscsi->tsih );
  538. request->itt = htonl ( iscsi->itt );
  539. /* cid left as zero */
  540. request->cmdsn = htonl ( iscsi->cmdsn );
  541. request->expstatsn = htonl ( iscsi->statsn + 1 );
  542. }
  543. /**
  544. * Complete iSCSI login request PDU transmission
  545. *
  546. * @v iscsi iSCSI session
  547. *
  548. */
  549. static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
  550. /* Clear any "strings to send" flags */
  551. iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
  552. /* Free any dynamically allocated storage used for login */
  553. chap_finish ( &iscsi->chap );
  554. }
  555. /**
  556. * Transmit data segment of an iSCSI login request PDU
  557. *
  558. * @v iscsi iSCSI session
  559. * @ret rc Return status code
  560. *
  561. * For login requests, the data segment consists of the login strings.
  562. */
  563. static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
  564. struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
  565. struct io_buffer *iobuf;
  566. size_t len;
  567. len = ISCSI_DATA_LEN ( request->lengths );
  568. iobuf = xfer_alloc_iob ( &iscsi->socket, len );
  569. if ( ! iobuf )
  570. return -ENOMEM;
  571. iob_put ( iobuf, len );
  572. iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
  573. return xfer_deliver_iob ( &iscsi->socket, iobuf );
  574. }
  575. /**
  576. * Calculate maximum length of decoded large binary value
  577. *
  578. * @v encoded Encoded large binary value
  579. * @v max_raw_len Maximum length of raw data
  580. */
  581. static inline size_t
  582. iscsi_large_binary_decoded_max_len ( const char *encoded ) {
  583. return ( strlen ( encoded ) ); /* Decoding never expands data */
  584. }
  585. /**
  586. * Decode large binary value
  587. *
  588. * @v encoded Encoded large binary value
  589. * @v raw Raw data
  590. * @ret len Length of raw data, or negative error
  591. */
  592. static int iscsi_large_binary_decode ( const char *encoded, uint8_t *raw ) {
  593. if ( encoded[0] != '0' )
  594. return -EPROTO_INVALID_LARGE_BINARY;
  595. switch ( encoded[1] ) {
  596. case 'x' :
  597. case 'X' :
  598. return base16_decode ( ( encoded + 2 ), raw );
  599. case 'b' :
  600. case 'B' :
  601. return base64_decode ( ( encoded + 2 ), raw );
  602. default:
  603. return -EPROTO_INVALID_LARGE_BINARY;
  604. }
  605. }
  606. /**
  607. * Handle iSCSI TargetAddress text value
  608. *
  609. * @v iscsi iSCSI session
  610. * @v value TargetAddress value
  611. * @ret rc Return status code
  612. */
  613. static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
  614. const char *value ) {
  615. char *separator;
  616. DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
  617. /* Replace target address */
  618. free ( iscsi->target_address );
  619. iscsi->target_address = strdup ( value );
  620. if ( ! iscsi->target_address )
  621. return -ENOMEM;
  622. /* Replace target port */
  623. iscsi->target_port = htons ( ISCSI_PORT );
  624. separator = strchr ( iscsi->target_address, ':' );
  625. if ( separator ) {
  626. *separator = '\0';
  627. iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
  628. }
  629. return 0;
  630. }
  631. /**
  632. * Handle iSCSI AuthMethod text value
  633. *
  634. * @v iscsi iSCSI session
  635. * @v value AuthMethod value
  636. * @ret rc Return status code
  637. */
  638. static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
  639. const char *value ) {
  640. /* If server requests CHAP, send the CHAP_A string */
  641. if ( strcmp ( value, "CHAP" ) == 0 ) {
  642. DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
  643. iscsi );
  644. iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
  645. ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
  646. }
  647. return 0;
  648. }
  649. /**
  650. * Handle iSCSI CHAP_A text value
  651. *
  652. * @v iscsi iSCSI session
  653. * @v value CHAP_A value
  654. * @ret rc Return status code
  655. */
  656. static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
  657. const char *value ) {
  658. /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
  659. * the server responds with anything else it is a protocol
  660. * violation.
  661. */
  662. if ( strcmp ( value, "5" ) != 0 ) {
  663. DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
  664. iscsi, value );
  665. return -EPROTO_INVALID_CHAP_ALGORITHM;
  666. }
  667. return 0;
  668. }
  669. /**
  670. * Handle iSCSI CHAP_I text value
  671. *
  672. * @v iscsi iSCSI session
  673. * @v value CHAP_I value
  674. * @ret rc Return status code
  675. */
  676. static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
  677. const char *value ) {
  678. unsigned int identifier;
  679. char *endp;
  680. int rc;
  681. /* The CHAP identifier is an integer value */
  682. identifier = strtoul ( value, &endp, 0 );
  683. if ( *endp != '\0' ) {
  684. DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
  685. iscsi, value );
  686. return -EPROTO_INVALID_CHAP_IDENTIFIER;
  687. }
  688. /* Prepare for CHAP with MD5 */
  689. chap_finish ( &iscsi->chap );
  690. if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
  691. DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
  692. iscsi, strerror ( rc ) );
  693. return rc;
  694. }
  695. /* Identifier and secret are the first two components of the
  696. * challenge.
  697. */
  698. chap_set_identifier ( &iscsi->chap, identifier );
  699. if ( iscsi->initiator_password ) {
  700. chap_update ( &iscsi->chap, iscsi->initiator_password,
  701. strlen ( iscsi->initiator_password ) );
  702. }
  703. return 0;
  704. }
  705. /**
  706. * Handle iSCSI CHAP_C text value
  707. *
  708. * @v iscsi iSCSI session
  709. * @v value CHAP_C value
  710. * @ret rc Return status code
  711. */
  712. static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
  713. const char *value ) {
  714. uint8_t buf[ iscsi_large_binary_decoded_max_len ( value ) ];
  715. unsigned int i;
  716. size_t len;
  717. int rc;
  718. /* Process challenge */
  719. rc = iscsi_large_binary_decode ( value, buf );
  720. if ( rc < 0 ) {
  721. DBGC ( iscsi, "iSCSI %p invalid CHAP challenge \"%s\": %s\n",
  722. iscsi, value, strerror ( rc ) );
  723. return rc;
  724. }
  725. len = rc;
  726. chap_update ( &iscsi->chap, buf, len );
  727. /* Build CHAP response */
  728. DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
  729. chap_respond ( &iscsi->chap );
  730. iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
  731. /* Send CHAP challenge, if applicable */
  732. if ( iscsi->target_username ) {
  733. iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
  734. /* Generate CHAP challenge data */
  735. for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
  736. iscsi->chap_challenge[i] = random();
  737. }
  738. }
  739. return 0;
  740. }
  741. /**
  742. * Handle iSCSI CHAP_N text value
  743. *
  744. * @v iscsi iSCSI session
  745. * @v value CHAP_N value
  746. * @ret rc Return status code
  747. */
  748. static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
  749. const char *value ) {
  750. /* The target username isn't actually involved at any point in
  751. * the authentication process; it merely serves to identify
  752. * which password the target is using to generate the CHAP
  753. * response. We unnecessarily verify that the username is as
  754. * expected, in order to provide mildly helpful diagnostics if
  755. * the target is supplying the wrong username/password
  756. * combination.
  757. */
  758. if ( iscsi->target_username &&
  759. ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
  760. DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
  761. "(wanted \"%s\")\n",
  762. iscsi, value, iscsi->target_username );
  763. return -EACCES_INCORRECT_TARGET_USERNAME;
  764. }
  765. return 0;
  766. }
  767. /**
  768. * Handle iSCSI CHAP_R text value
  769. *
  770. * @v iscsi iSCSI session
  771. * @v value CHAP_R value
  772. * @ret rc Return status code
  773. */
  774. static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
  775. const char *value ) {
  776. uint8_t buf[ iscsi_large_binary_decoded_max_len ( value ) ];
  777. size_t len;
  778. int rc;
  779. /* Generate CHAP response for verification */
  780. chap_finish ( &iscsi->chap );
  781. if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
  782. DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
  783. iscsi, strerror ( rc ) );
  784. return rc;
  785. }
  786. chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
  787. if ( iscsi->target_password ) {
  788. chap_update ( &iscsi->chap, iscsi->target_password,
  789. strlen ( iscsi->target_password ) );
  790. }
  791. chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
  792. ( sizeof ( iscsi->chap_challenge ) - 1 ) );
  793. chap_respond ( &iscsi->chap );
  794. /* Process response */
  795. rc = iscsi_large_binary_decode ( value, buf );
  796. if ( rc < 0 ) {
  797. DBGC ( iscsi, "iSCSI %p invalid CHAP response \"%s\": %s\n",
  798. iscsi, value, strerror ( rc ) );
  799. return rc;
  800. }
  801. len = rc;
  802. /* Check CHAP response */
  803. if ( len != iscsi->chap.response_len ) {
  804. DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
  805. iscsi );
  806. return -EPROTO_INVALID_CHAP_RESPONSE;
  807. }
  808. if ( memcmp ( buf, iscsi->chap.response, len ) != 0 ) {
  809. DBGC ( iscsi, "iSCSI %p incorrect CHAP response \"%s\"\n",
  810. iscsi, value );
  811. return -EACCES_INCORRECT_TARGET_PASSWORD;
  812. }
  813. /* Mark session as authenticated */
  814. iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
  815. return 0;
  816. }
  817. /** An iSCSI text string that we want to handle */
  818. struct iscsi_string_type {
  819. /** String key
  820. *
  821. * This is the portion up to and including the "=" sign,
  822. * e.g. "InitiatorName=", "CHAP_A=", etc.
  823. */
  824. const char *key;
  825. /** Handle iSCSI string value
  826. *
  827. * @v iscsi iSCSI session
  828. * @v value iSCSI string value
  829. * @ret rc Return status code
  830. */
  831. int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
  832. };
  833. /** iSCSI text strings that we want to handle */
  834. static struct iscsi_string_type iscsi_string_types[] = {
  835. { "TargetAddress=", iscsi_handle_targetaddress_value },
  836. { "AuthMethod=", iscsi_handle_authmethod_value },
  837. { "CHAP_A=", iscsi_handle_chap_a_value },
  838. { "CHAP_I=", iscsi_handle_chap_i_value },
  839. { "CHAP_C=", iscsi_handle_chap_c_value },
  840. { "CHAP_N=", iscsi_handle_chap_n_value },
  841. { "CHAP_R=", iscsi_handle_chap_r_value },
  842. { NULL, NULL }
  843. };
  844. /**
  845. * Handle iSCSI string
  846. *
  847. * @v iscsi iSCSI session
  848. * @v string iSCSI string (in "key=value" format)
  849. * @ret rc Return status code
  850. */
  851. static int iscsi_handle_string ( struct iscsi_session *iscsi,
  852. const char *string ) {
  853. struct iscsi_string_type *type;
  854. size_t key_len;
  855. int rc;
  856. for ( type = iscsi_string_types ; type->key ; type++ ) {
  857. key_len = strlen ( type->key );
  858. if ( strncmp ( string, type->key, key_len ) != 0 )
  859. continue;
  860. DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
  861. if ( ( rc = type->handle ( iscsi,
  862. ( string + key_len ) ) ) != 0 ) {
  863. DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
  864. iscsi, string, strerror ( rc ) );
  865. return rc;
  866. }
  867. return 0;
  868. }
  869. DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
  870. return 0;
  871. }
  872. /**
  873. * Handle iSCSI strings
  874. *
  875. * @v iscsi iSCSI session
  876. * @v string iSCSI string buffer
  877. * @v len Length of string buffer
  878. * @ret rc Return status code
  879. */
  880. static int iscsi_handle_strings ( struct iscsi_session *iscsi,
  881. const char *strings, size_t len ) {
  882. size_t string_len;
  883. int rc;
  884. /* Handle each string in turn, taking care not to overrun the
  885. * data buffer in case of badly-terminated data.
  886. */
  887. while ( 1 ) {
  888. string_len = ( strnlen ( strings, len ) + 1 );
  889. if ( string_len > len )
  890. break;
  891. if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
  892. return rc;
  893. strings += string_len;
  894. len -= string_len;
  895. }
  896. return 0;
  897. }
  898. /**
  899. * Receive PDU data into buffer
  900. *
  901. * @v iscsi iSCSI session
  902. * @v data Data to receive
  903. * @v len Length of data
  904. * @ret rc Return status code
  905. *
  906. * This can be used when the RX PDU type handler wishes to buffer up
  907. * all received data and process the PDU as a single unit. The caller
  908. * is repsonsible for calling iscsi_rx_buffered_data_done() after
  909. * processing the data.
  910. */
  911. static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
  912. const void *data, size_t len ) {
  913. /* Allocate buffer on first call */
  914. if ( ! iscsi->rx_buffer ) {
  915. iscsi->rx_buffer = malloc ( iscsi->rx_len );
  916. if ( ! iscsi->rx_buffer )
  917. return -ENOMEM;
  918. }
  919. /* Copy data to buffer */
  920. assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
  921. memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
  922. return 0;
  923. }
  924. /**
  925. * Convert iSCSI response status to return status code
  926. *
  927. * @v status_class iSCSI status class
  928. * @v status_detail iSCSI status detail
  929. * @ret rc Return status code
  930. */
  931. static int iscsi_status_to_rc ( unsigned int status_class,
  932. unsigned int status_detail ) {
  933. switch ( status_class ) {
  934. case ISCSI_STATUS_INITIATOR_ERROR :
  935. switch ( status_detail ) {
  936. case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
  937. return -EPERM_INITIATOR_AUTHENTICATION;
  938. case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
  939. return -EPERM_INITIATOR_AUTHORISATION;
  940. case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
  941. case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
  942. return -ENODEV;
  943. default :
  944. return -ENOTSUP_INITIATOR_STATUS;
  945. }
  946. case ISCSI_STATUS_TARGET_ERROR :
  947. return -EIO;
  948. default :
  949. return -EINVAL;
  950. }
  951. }
  952. /**
  953. * Receive data segment of an iSCSI login response PDU
  954. *
  955. * @v iscsi iSCSI session
  956. * @v data Received data
  957. * @v len Length of received data
  958. * @v remaining Data remaining after this data
  959. * @ret rc Return status code
  960. */
  961. static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
  962. const void *data, size_t len,
  963. size_t remaining ) {
  964. struct iscsi_bhs_login_response *response
  965. = &iscsi->rx_bhs.login_response;
  966. int rc;
  967. /* Buffer up the PDU data */
  968. if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
  969. DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
  970. iscsi, strerror ( rc ) );
  971. return rc;
  972. }
  973. if ( remaining )
  974. return 0;
  975. /* Process string data and discard string buffer */
  976. if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
  977. iscsi->rx_len ) ) != 0 )
  978. return rc;
  979. iscsi_rx_buffered_data_done ( iscsi );
  980. /* Check for login redirection */
  981. if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
  982. DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
  983. iscsi_close_connection ( iscsi, 0 );
  984. if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
  985. DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
  986. iscsi, strerror ( rc ) );
  987. return rc;
  988. }
  989. return 0;
  990. }
  991. /* Check for fatal errors */
  992. if ( response->status_class != 0 ) {
  993. DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
  994. response->status_class, response->status_detail );
  995. rc = iscsi_status_to_rc ( response->status_class,
  996. response->status_detail );
  997. iscsi->instant_rc = rc;
  998. return rc;
  999. }
  1000. /* Handle login transitions */
  1001. if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
  1002. iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
  1003. ISCSI_STATUS_STRINGS_MASK );
  1004. switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
  1005. case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
  1006. iscsi->status |=
  1007. ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
  1008. ISCSI_STATUS_STRINGS_OPERATIONAL );
  1009. break;
  1010. case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
  1011. iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
  1012. break;
  1013. default:
  1014. DBGC ( iscsi, "iSCSI %p got invalid response flags "
  1015. "%02x\n", iscsi, response->flags );
  1016. return -EIO;
  1017. }
  1018. }
  1019. /* Send next login request PDU if we haven't reached the full
  1020. * feature phase yet.
  1021. */
  1022. if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
  1023. ISCSI_STATUS_FULL_FEATURE_PHASE ) {
  1024. iscsi_start_login ( iscsi );
  1025. return 0;
  1026. }
  1027. /* Check that target authentication was successful (if required) */
  1028. if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
  1029. ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
  1030. DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
  1031. "authentication\n", iscsi );
  1032. return -EPROTO;
  1033. }
  1034. /* Reset retry count */
  1035. iscsi->retry_count = 0;
  1036. /* Record TSIH for future reference */
  1037. iscsi->tsih = ntohl ( response->tsih );
  1038. /* Send the actual SCSI command */
  1039. iscsi_start_command ( iscsi );
  1040. return 0;
  1041. }
  1042. /****************************************************************************
  1043. *
  1044. * iSCSI to socket interface
  1045. *
  1046. */
  1047. /**
  1048. * Start up a new TX PDU
  1049. *
  1050. * @v iscsi iSCSI session
  1051. *
  1052. * This initiates the process of sending a new PDU. Only one PDU may
  1053. * be in transit at any one time.
  1054. */
  1055. static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
  1056. assert ( iscsi->tx_state == ISCSI_TX_IDLE );
  1057. /* Initialise TX BHS */
  1058. memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
  1059. /* Flag TX engine to start transmitting */
  1060. iscsi->tx_state = ISCSI_TX_BHS;
  1061. }
  1062. /**
  1063. * Transmit nothing
  1064. *
  1065. * @v iscsi iSCSI session
  1066. * @ret rc Return status code
  1067. */
  1068. static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
  1069. return 0;
  1070. }
  1071. /**
  1072. * Transmit basic header segment of an iSCSI PDU
  1073. *
  1074. * @v iscsi iSCSI session
  1075. * @ret rc Return status code
  1076. */
  1077. static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
  1078. return xfer_deliver_raw ( &iscsi->socket, &iscsi->tx_bhs,
  1079. sizeof ( iscsi->tx_bhs ) );
  1080. }
  1081. /**
  1082. * Transmit data segment of an iSCSI PDU
  1083. *
  1084. * @v iscsi iSCSI session
  1085. * @ret rc Return status code
  1086. *
  1087. * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
  1088. * will be valid when this is called.
  1089. */
  1090. static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
  1091. struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
  1092. switch ( common->opcode & ISCSI_OPCODE_MASK ) {
  1093. case ISCSI_OPCODE_DATA_OUT:
  1094. return iscsi_tx_data_out ( iscsi );
  1095. case ISCSI_OPCODE_LOGIN_REQUEST:
  1096. return iscsi_tx_login_request ( iscsi );
  1097. default:
  1098. /* Nothing to send in other states */
  1099. return 0;
  1100. }
  1101. }
  1102. /**
  1103. * Transmit data padding of an iSCSI PDU
  1104. *
  1105. * @v iscsi iSCSI session
  1106. * @ret rc Return status code
  1107. *
  1108. * Handle transmission of any data padding in a PDU data segment.
  1109. * iscsi::tx_bhs will be valid when this is called.
  1110. */
  1111. static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
  1112. static const char pad[] = { '\0', '\0', '\0' };
  1113. struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
  1114. size_t pad_len;
  1115. pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
  1116. if ( ! pad_len )
  1117. return 0;
  1118. return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
  1119. }
  1120. /**
  1121. * Complete iSCSI PDU transmission
  1122. *
  1123. * @v iscsi iSCSI session
  1124. *
  1125. * Called when a PDU has been completely transmitted and the TX state
  1126. * machine is about to enter the idle state. iscsi::tx_bhs will be
  1127. * valid for the just-completed PDU when this is called.
  1128. */
  1129. static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
  1130. struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
  1131. switch ( common->opcode & ISCSI_OPCODE_MASK ) {
  1132. case ISCSI_OPCODE_DATA_OUT:
  1133. iscsi_data_out_done ( iscsi );
  1134. case ISCSI_OPCODE_LOGIN_REQUEST:
  1135. iscsi_login_request_done ( iscsi );
  1136. default:
  1137. /* No action */
  1138. break;
  1139. }
  1140. }
  1141. /**
  1142. * Transmit iSCSI PDU
  1143. *
  1144. * @v iscsi iSCSI session
  1145. * @v buf Temporary data buffer
  1146. * @v len Length of temporary data buffer
  1147. *
  1148. * Constructs data to be sent for the current TX state
  1149. */
  1150. static void iscsi_tx_step ( struct process *process ) {
  1151. struct iscsi_session *iscsi =
  1152. container_of ( process, struct iscsi_session, process );
  1153. struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
  1154. int ( * tx ) ( struct iscsi_session *iscsi );
  1155. enum iscsi_tx_state next_state;
  1156. size_t tx_len;
  1157. int rc;
  1158. /* Select fragment to transmit */
  1159. while ( 1 ) {
  1160. switch ( iscsi->tx_state ) {
  1161. case ISCSI_TX_IDLE:
  1162. /* Stop processing */
  1163. return;
  1164. case ISCSI_TX_BHS:
  1165. tx = iscsi_tx_bhs;
  1166. tx_len = sizeof ( iscsi->tx_bhs );
  1167. next_state = ISCSI_TX_AHS;
  1168. break;
  1169. case ISCSI_TX_AHS:
  1170. tx = iscsi_tx_nothing;
  1171. tx_len = 0;
  1172. next_state = ISCSI_TX_DATA;
  1173. break;
  1174. case ISCSI_TX_DATA:
  1175. tx = iscsi_tx_data;
  1176. tx_len = ISCSI_DATA_LEN ( common->lengths );
  1177. next_state = ISCSI_TX_DATA_PADDING;
  1178. break;
  1179. case ISCSI_TX_DATA_PADDING:
  1180. tx = iscsi_tx_data_padding;
  1181. tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
  1182. next_state = ISCSI_TX_IDLE;
  1183. break;
  1184. default:
  1185. assert ( 0 );
  1186. return;
  1187. }
  1188. /* Check for window availability, if needed */
  1189. if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
  1190. /* Cannot transmit at this point; stop processing */
  1191. return;
  1192. }
  1193. /* Transmit data */
  1194. if ( ( rc = tx ( iscsi ) ) != 0 ) {
  1195. DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
  1196. iscsi, strerror ( rc ) );
  1197. return;
  1198. }
  1199. /* Move to next state */
  1200. iscsi->tx_state = next_state;
  1201. if ( next_state == ISCSI_TX_IDLE )
  1202. iscsi_tx_done ( iscsi );
  1203. }
  1204. }
  1205. /**
  1206. * Receive basic header segment of an iSCSI PDU
  1207. *
  1208. * @v iscsi iSCSI session
  1209. * @v data Received data
  1210. * @v len Length of received data
  1211. * @v remaining Data remaining after this data
  1212. * @ret rc Return status code
  1213. *
  1214. * This fills in iscsi::rx_bhs with the data from the BHS portion of
  1215. * the received PDU.
  1216. */
  1217. static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
  1218. size_t len, size_t remaining __unused ) {
  1219. memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
  1220. if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
  1221. DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
  1222. iscsi, iscsi->rx_bhs.common.opcode,
  1223. ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
  1224. }
  1225. return 0;
  1226. }
  1227. /**
  1228. * Discard portion of an iSCSI PDU.
  1229. *
  1230. * @v iscsi iSCSI session
  1231. * @v data Received data
  1232. * @v len Length of received data
  1233. * @v remaining Data remaining after this data
  1234. * @ret rc Return status code
  1235. *
  1236. * This discards data from a portion of a received PDU.
  1237. */
  1238. static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
  1239. const void *data __unused, size_t len __unused,
  1240. size_t remaining __unused ) {
  1241. /* Do nothing */
  1242. return 0;
  1243. }
  1244. /**
  1245. * Receive data segment of an iSCSI PDU
  1246. *
  1247. * @v iscsi iSCSI session
  1248. * @v data Received data
  1249. * @v len Length of received data
  1250. * @v remaining Data remaining after this data
  1251. * @ret rc Return status code
  1252. *
  1253. * Handle processing of part of a PDU data segment. iscsi::rx_bhs
  1254. * will be valid when this is called.
  1255. */
  1256. static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
  1257. size_t len, size_t remaining ) {
  1258. struct iscsi_bhs_common_response *response
  1259. = &iscsi->rx_bhs.common_response;
  1260. /* Update cmdsn and statsn */
  1261. iscsi->cmdsn = ntohl ( response->expcmdsn );
  1262. iscsi->statsn = ntohl ( response->statsn );
  1263. switch ( response->opcode & ISCSI_OPCODE_MASK ) {
  1264. case ISCSI_OPCODE_LOGIN_RESPONSE:
  1265. return iscsi_rx_login_response ( iscsi, data, len, remaining );
  1266. case ISCSI_OPCODE_SCSI_RESPONSE:
  1267. return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
  1268. case ISCSI_OPCODE_DATA_IN:
  1269. return iscsi_rx_data_in ( iscsi, data, len, remaining );
  1270. case ISCSI_OPCODE_R2T:
  1271. return iscsi_rx_r2t ( iscsi, data, len, remaining );
  1272. default:
  1273. if ( remaining )
  1274. return 0;
  1275. DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
  1276. response->opcode );
  1277. return -ENOTSUP_OPCODE;
  1278. }
  1279. }
  1280. /**
  1281. * Receive new data
  1282. *
  1283. * @v socket Transport layer interface
  1284. * @v data Received data
  1285. * @v len Length of received data
  1286. * @ret rc Return status code
  1287. *
  1288. * This handles received PDUs. The receive strategy is to fill in
  1289. * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
  1290. * throw away any AHS portion, and then process each part of the data
  1291. * portion as it arrives. The data processing routine therefore
  1292. * always has a full copy of the BHS available, even for portions of
  1293. * the data in different packets to the BHS.
  1294. */
  1295. static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
  1296. const void *data, size_t len ) {
  1297. struct iscsi_session *iscsi =
  1298. container_of ( socket, struct iscsi_session, socket );
  1299. struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
  1300. int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
  1301. size_t len, size_t remaining );
  1302. enum iscsi_rx_state next_state;
  1303. size_t frag_len;
  1304. size_t remaining;
  1305. int rc;
  1306. while ( 1 ) {
  1307. switch ( iscsi->rx_state ) {
  1308. case ISCSI_RX_BHS:
  1309. rx = iscsi_rx_bhs;
  1310. iscsi->rx_len = sizeof ( iscsi->rx_bhs );
  1311. next_state = ISCSI_RX_AHS;
  1312. break;
  1313. case ISCSI_RX_AHS:
  1314. rx = iscsi_rx_discard;
  1315. iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
  1316. next_state = ISCSI_RX_DATA;
  1317. break;
  1318. case ISCSI_RX_DATA:
  1319. rx = iscsi_rx_data;
  1320. iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
  1321. next_state = ISCSI_RX_DATA_PADDING;
  1322. break;
  1323. case ISCSI_RX_DATA_PADDING:
  1324. rx = iscsi_rx_discard;
  1325. iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
  1326. next_state = ISCSI_RX_BHS;
  1327. break;
  1328. default:
  1329. assert ( 0 );
  1330. return -EINVAL;
  1331. }
  1332. frag_len = iscsi->rx_len - iscsi->rx_offset;
  1333. if ( frag_len > len )
  1334. frag_len = len;
  1335. remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
  1336. if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
  1337. DBGC ( iscsi, "iSCSI %p could not process received "
  1338. "data: %s\n", iscsi, strerror ( rc ) );
  1339. iscsi_close_connection ( iscsi, rc );
  1340. iscsi_scsi_done ( iscsi, rc );
  1341. return rc;
  1342. }
  1343. iscsi->rx_offset += frag_len;
  1344. data += frag_len;
  1345. len -= frag_len;
  1346. /* If all the data for this state has not yet been
  1347. * received, stay in this state for now.
  1348. */
  1349. if ( iscsi->rx_offset != iscsi->rx_len )
  1350. return 0;
  1351. iscsi->rx_state = next_state;
  1352. iscsi->rx_offset = 0;
  1353. }
  1354. return 0;
  1355. }
  1356. /**
  1357. * Handle stream connection closure
  1358. *
  1359. * @v socket Transport layer interface
  1360. * @v rc Reason for close
  1361. *
  1362. */
  1363. static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
  1364. struct iscsi_session *iscsi =
  1365. container_of ( socket, struct iscsi_session, socket );
  1366. /* Even a graceful close counts as an error for iSCSI */
  1367. if ( ! rc )
  1368. rc = -ECONNRESET;
  1369. /* Close session cleanly */
  1370. iscsi_close_connection ( iscsi, rc );
  1371. /* Retry connection if within the retry limit, otherwise fail */
  1372. if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
  1373. DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
  1374. iscsi, iscsi->retry_count );
  1375. if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
  1376. DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
  1377. iscsi, strerror ( rc ) );
  1378. iscsi_scsi_done ( iscsi, rc );
  1379. }
  1380. } else {
  1381. DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
  1382. iscsi->instant_rc = rc;
  1383. iscsi_scsi_done ( iscsi, rc );
  1384. }
  1385. }
  1386. /**
  1387. * Handle redirection event
  1388. *
  1389. * @v socket Transport layer interface
  1390. * @v type Location type
  1391. * @v args Remaining arguments depend upon location type
  1392. * @ret rc Return status code
  1393. */
  1394. static int iscsi_vredirect ( struct xfer_interface *socket, int type,
  1395. va_list args ) {
  1396. struct iscsi_session *iscsi =
  1397. container_of ( socket, struct iscsi_session, socket );
  1398. va_list tmp;
  1399. struct sockaddr *peer;
  1400. /* Intercept redirects to a LOCATION_SOCKET and record the IP
  1401. * address for the iBFT. This is a bit of a hack, but avoids
  1402. * inventing an ioctl()-style call to retrieve the socket
  1403. * address from a data-xfer interface.
  1404. */
  1405. if ( type == LOCATION_SOCKET ) {
  1406. va_copy ( tmp, args );
  1407. ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
  1408. peer = va_arg ( tmp, struct sockaddr * );
  1409. memcpy ( &iscsi->target_sockaddr, peer,
  1410. sizeof ( iscsi->target_sockaddr ) );
  1411. va_end ( tmp );
  1412. }
  1413. return xfer_vreopen ( socket, type, args );
  1414. }
  1415. /** iSCSI socket operations */
  1416. static struct xfer_interface_operations iscsi_socket_operations = {
  1417. .close = iscsi_socket_close,
  1418. .vredirect = iscsi_vredirect,
  1419. .window = unlimited_xfer_window,
  1420. .alloc_iob = default_xfer_alloc_iob,
  1421. .deliver_iob = xfer_deliver_as_raw,
  1422. .deliver_raw = iscsi_socket_deliver_raw,
  1423. };
  1424. /****************************************************************************
  1425. *
  1426. * iSCSI command issuing
  1427. *
  1428. */
  1429. /**
  1430. * Issue SCSI command
  1431. *
  1432. * @v scsi SCSI device
  1433. * @v command SCSI command
  1434. * @ret rc Return status code
  1435. */
  1436. static int iscsi_command ( struct scsi_device *scsi,
  1437. struct scsi_command *command ) {
  1438. struct iscsi_session *iscsi =
  1439. container_of ( scsi->backend, struct iscsi_session, refcnt );
  1440. int rc;
  1441. /* Abort immediately if we have a recorded permanent failure */
  1442. if ( iscsi->instant_rc )
  1443. return iscsi->instant_rc;
  1444. /* Record SCSI command */
  1445. iscsi->command = command;
  1446. /* Issue command or open connection as appropriate */
  1447. if ( iscsi->status ) {
  1448. iscsi_start_command ( iscsi );
  1449. } else {
  1450. if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
  1451. iscsi->command = NULL;
  1452. return rc;
  1453. }
  1454. }
  1455. return 0;
  1456. }
  1457. /**
  1458. * Shut down iSCSI interface
  1459. *
  1460. * @v scsi SCSI device
  1461. */
  1462. void iscsi_detach ( struct scsi_device *scsi ) {
  1463. struct iscsi_session *iscsi =
  1464. container_of ( scsi->backend, struct iscsi_session, refcnt );
  1465. xfer_nullify ( &iscsi->socket );
  1466. iscsi_close_connection ( iscsi, 0 );
  1467. process_del ( &iscsi->process );
  1468. scsi->command = scsi_detached_command;
  1469. ref_put ( scsi->backend );
  1470. scsi->backend = NULL;
  1471. }
  1472. /****************************************************************************
  1473. *
  1474. * Instantiator
  1475. *
  1476. */
  1477. /** iSCSI root path components (as per RFC4173) */
  1478. enum iscsi_root_path_component {
  1479. RP_LITERAL = 0,
  1480. RP_SERVERNAME,
  1481. RP_PROTOCOL,
  1482. RP_PORT,
  1483. RP_LUN,
  1484. RP_TARGETNAME,
  1485. NUM_RP_COMPONENTS
  1486. };
  1487. /**
  1488. * Parse iSCSI root path
  1489. *
  1490. * @v iscsi iSCSI session
  1491. * @v root_path iSCSI root path (as per RFC4173)
  1492. * @ret rc Return status code
  1493. */
  1494. static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
  1495. const char *root_path ) {
  1496. char rp_copy[ strlen ( root_path ) + 1 ];
  1497. char *rp_comp[NUM_RP_COMPONENTS];
  1498. char *rp = rp_copy;
  1499. int i = 0;
  1500. int rc;
  1501. /* Split root path into component parts */
  1502. strcpy ( rp_copy, root_path );
  1503. while ( 1 ) {
  1504. rp_comp[i++] = rp;
  1505. if ( i == NUM_RP_COMPONENTS )
  1506. break;
  1507. for ( ; *rp != ':' ; rp++ ) {
  1508. if ( ! *rp ) {
  1509. DBGC ( iscsi, "iSCSI %p root path \"%s\" "
  1510. "too short\n", iscsi, root_path );
  1511. return -EINVAL;
  1512. }
  1513. }
  1514. *(rp++) = '\0';
  1515. }
  1516. /* Use root path components to configure iSCSI session */
  1517. iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
  1518. if ( ! iscsi->target_address )
  1519. return -ENOMEM;
  1520. iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
  1521. if ( ! iscsi->target_port )
  1522. iscsi->target_port = ISCSI_PORT;
  1523. if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
  1524. DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
  1525. iscsi, rp_comp[RP_LUN] );
  1526. return rc;
  1527. }
  1528. iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
  1529. if ( ! iscsi->target_iqn )
  1530. return -ENOMEM;
  1531. return 0;
  1532. }
  1533. /**
  1534. * Set iSCSI authentication details
  1535. *
  1536. * @v iscsi iSCSI session
  1537. * @v initiator_username Initiator username, if any
  1538. * @v initiator_password Initiator password, if any
  1539. * @v target_username Target username, if any
  1540. * @v target_password Target password, if any
  1541. * @ret rc Return status code
  1542. */
  1543. static int iscsi_set_auth ( struct iscsi_session *iscsi,
  1544. const char *initiator_username,
  1545. const char *initiator_password,
  1546. const char *target_username,
  1547. const char *target_password ) {
  1548. /* Check for initiator or target credentials */
  1549. if ( initiator_username || initiator_password ||
  1550. target_username || target_password ) {
  1551. /* We must have at least an initiator username+password */
  1552. if ( ! ( initiator_username && initiator_password ) )
  1553. goto invalid_auth;
  1554. /* Store initiator credentials */
  1555. iscsi->initiator_username = strdup ( initiator_username );
  1556. if ( ! iscsi->initiator_username )
  1557. return -ENOMEM;
  1558. iscsi->initiator_password = strdup ( initiator_password );
  1559. if ( ! iscsi->initiator_password )
  1560. return -ENOMEM;
  1561. /* Check for target credentials */
  1562. if ( target_username || target_password ) {
  1563. /* We must have target username+password */
  1564. if ( ! ( target_username && target_password ) )
  1565. goto invalid_auth;
  1566. /* Store target credentials */
  1567. iscsi->target_username = strdup ( target_username );
  1568. if ( ! iscsi->target_username )
  1569. return -ENOMEM;
  1570. iscsi->target_password = strdup ( target_password );
  1571. if ( ! iscsi->target_password )
  1572. return -ENOMEM;
  1573. }
  1574. }
  1575. return 0;
  1576. invalid_auth:
  1577. DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
  1578. "%sname,%spw, target %sname,%spw\n", iscsi,
  1579. ( initiator_username ? "" : "no " ),
  1580. ( initiator_password ? "" : "no " ),
  1581. ( target_username ? "" : "no " ),
  1582. ( target_password ? "" : "no " ) );
  1583. return -EINVAL;
  1584. }
  1585. /**
  1586. * Attach iSCSI interface
  1587. *
  1588. * @v scsi SCSI device
  1589. * @v root_path iSCSI root path (as per RFC4173)
  1590. * @ret rc Return status code
  1591. */
  1592. int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
  1593. struct iscsi_session *iscsi;
  1594. int rc;
  1595. /* Allocate and initialise structure */
  1596. iscsi = zalloc ( sizeof ( *iscsi ) );
  1597. if ( ! iscsi )
  1598. return -ENOMEM;
  1599. iscsi->refcnt.free = iscsi_free;
  1600. xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt );
  1601. process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
  1602. /* Parse root path */
  1603. if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
  1604. goto err;
  1605. /* Set fields not specified by root path */
  1606. if ( ( rc = iscsi_set_auth ( iscsi,
  1607. iscsi_initiator_username,
  1608. iscsi_initiator_password,
  1609. iscsi_target_username,
  1610. iscsi_target_password ) ) != 0 )
  1611. goto err;
  1612. /* Sanity checks */
  1613. if ( ! iscsi->target_address ) {
  1614. DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
  1615. iscsi );
  1616. rc = -ENOTSUP_DISCOVERY;
  1617. goto err;
  1618. }
  1619. if ( ! iscsi->target_iqn ) {
  1620. DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
  1621. iscsi, root_path );
  1622. rc = -EINVAL;
  1623. goto err;
  1624. }
  1625. /* Attach parent interface, mortalise self, and return */
  1626. scsi->backend = ref_get ( &iscsi->refcnt );
  1627. scsi->command = iscsi_command;
  1628. ref_put ( &iscsi->refcnt );
  1629. return 0;
  1630. err:
  1631. ref_put ( &iscsi->refcnt );
  1632. return rc;
  1633. }
  1634. /****************************************************************************
  1635. *
  1636. * Settings
  1637. *
  1638. */
  1639. /** iSCSI initiator IQN setting */
  1640. struct setting initiator_iqn_setting __setting = {
  1641. .name = "initiator-iqn",
  1642. .description = "iSCSI initiator name",
  1643. .tag = DHCP_ISCSI_INITIATOR_IQN,
  1644. .type = &setting_type_string,
  1645. };
  1646. /** iSCSI reverse username setting */
  1647. struct setting reverse_username_setting __setting = {
  1648. .name = "reverse-username",
  1649. .description = "Reverse user name",
  1650. .tag = DHCP_EB_REVERSE_USERNAME,
  1651. .type = &setting_type_string,
  1652. };
  1653. /** iSCSI reverse password setting */
  1654. struct setting reverse_password_setting __setting = {
  1655. .name = "reverse-password",
  1656. .description = "Reverse password",
  1657. .tag = DHCP_EB_REVERSE_PASSWORD,
  1658. .type = &setting_type_string,
  1659. };
  1660. /** An iSCSI string setting */
  1661. struct iscsi_string_setting {
  1662. /** Setting */
  1663. struct setting *setting;
  1664. /** String to update */
  1665. char **string;
  1666. /** String prefix */
  1667. const char *prefix;
  1668. };
  1669. /** iSCSI string settings */
  1670. static struct iscsi_string_setting iscsi_string_settings[] = {
  1671. {
  1672. .setting = &initiator_iqn_setting,
  1673. .string = &iscsi_explicit_initiator_iqn,
  1674. .prefix = "",
  1675. },
  1676. {
  1677. .setting = &username_setting,
  1678. .string = &iscsi_initiator_username,
  1679. .prefix = "",
  1680. },
  1681. {
  1682. .setting = &password_setting,
  1683. .string = &iscsi_initiator_password,
  1684. .prefix = "",
  1685. },
  1686. {
  1687. .setting = &reverse_username_setting,
  1688. .string = &iscsi_target_username,
  1689. .prefix = "",
  1690. },
  1691. {
  1692. .setting = &reverse_password_setting,
  1693. .string = &iscsi_target_password,
  1694. .prefix = "",
  1695. },
  1696. {
  1697. .setting = &hostname_setting,
  1698. .string = &iscsi_default_initiator_iqn,
  1699. .prefix = "iqn.2000-01.org.etherboot:",
  1700. },
  1701. };
  1702. /**
  1703. * Apply iSCSI setting
  1704. *
  1705. * @v setting iSCSI string setting
  1706. * @ret rc Return status code
  1707. */
  1708. static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
  1709. size_t prefix_len;
  1710. int setting_len;
  1711. size_t len;
  1712. int check_len;
  1713. char *p;
  1714. /* Free old string */
  1715. free ( *setting->string );
  1716. *setting->string = NULL;
  1717. /* Allocate new string */
  1718. prefix_len = strlen ( setting->prefix );
  1719. setting_len = fetch_setting_len ( NULL, setting->setting );
  1720. if ( setting_len < 0 ) {
  1721. /* Missing settings are not errors; leave strings as NULL */
  1722. return 0;
  1723. }
  1724. len = ( prefix_len + setting_len + 1 );
  1725. p = *setting->string = malloc ( len );
  1726. if ( ! p )
  1727. return -ENOMEM;
  1728. /* Fill new string */
  1729. strcpy ( p, setting->prefix );
  1730. check_len = fetch_string_setting ( NULL, setting->setting,
  1731. ( p + prefix_len ),
  1732. ( len - prefix_len ) );
  1733. assert ( check_len == setting_len );
  1734. return 0;
  1735. }
  1736. /**
  1737. * Apply iSCSI settings
  1738. *
  1739. * @ret rc Return status code
  1740. */
  1741. static int apply_iscsi_settings ( void ) {
  1742. struct iscsi_string_setting *setting;
  1743. unsigned int i;
  1744. int rc;
  1745. for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
  1746. sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
  1747. setting = &iscsi_string_settings[i];
  1748. if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
  1749. DBG ( "iSCSI could not apply setting %s\n",
  1750. setting->setting->name );
  1751. return rc;
  1752. }
  1753. }
  1754. return 0;
  1755. }
  1756. /** iSCSI settings applicator */
  1757. struct settings_applicator iscsi_settings_applicator __settings_applicator = {
  1758. .apply = apply_iscsi_settings,
  1759. };
  1760. /****************************************************************************
  1761. *
  1762. * Initiator name
  1763. *
  1764. */
  1765. /**
  1766. * Get iSCSI initiator IQN
  1767. *
  1768. * @v iscsi iSCSI session
  1769. * @ret rc Return status code
  1770. */
  1771. const char * iscsi_initiator_iqn ( void ) {
  1772. if ( iscsi_explicit_initiator_iqn )
  1773. return iscsi_explicit_initiator_iqn;
  1774. if ( iscsi_default_initiator_iqn )
  1775. return iscsi_default_initiator_iqn;
  1776. return "iqn.2000-09.org.etherboot:UNKNOWN";
  1777. }