1 /* 2 * iscsi - scsi over tcp/ip 3 * 4 * observations: 5 * iscsi names may be 223 bytes long. 6 * two namespaces, "iqn." and "eui.". 7 * don't need FIM when using tcp. 8 * rfc3720 §3.2.8.1 demonstrates that the authors don't understand (or 9 * don't trust) tcp: data isn't quietly dropped. 10 * 11 * we're not going to implement the optional digests (crcs), 12 * so those are omitted. 13 */ 14 15 enum { 16 Bhdrsz = 48, 17 18 /* initiator opcodes (requests) */ 19 Iopnopout= 0, 20 Iopcmd, 21 Ioptask, 22 Ioplogin, 23 Ioptext, 24 Iopdataout, /* write */ 25 Ioplogout, 26 Iopsnack= 0x10, 27 28 /* target opcodes (responses) */ 29 Topnopin= 0x20, 30 Topresp, 31 Toptask, 32 Toplogin, 33 Toptext, 34 Topdatain, /* read */ 35 Toplogout, 36 Topr2t = 0x31, 37 Topasync, 38 Topreject= 0x3f, 39 40 Immed = 1<<6, 41 Oprsrvd = 1<<7, 42 43 /* opspfc */ 44 Finalpkt= 1<<7, 45 }; 46 47 typedef struct Datainpkt Datainpkt; 48 typedef struct Iscsiasynch Iscsiasynch; 49 typedef struct Iscsicmdreq Iscsicmdreq; 50 typedef struct Iscsicmdresp Iscsicmdresp; 51 typedef struct Iscsidatain Iscsidatain; 52 typedef struct Iscsidataout Iscsidataout; 53 typedef struct Iscsijustbhdr Iscsijustbhdr; 54 typedef struct Iscsiloginreq Iscsiloginreq; 55 typedef struct Iscsiloginresp Iscsiloginresp; 56 typedef struct Iscsilogoutreq Iscsilogoutreq; 57 typedef struct Iscsilogoutresp Iscsilogoutresp; 58 typedef struct Iscsinopreq Iscsinopreq; /* nop out */ 59 typedef struct Iscsinopresp Iscsinopresp; /* nop in */ 60 typedef struct Iscsiready Iscsiready; 61 typedef struct Iscsireject Iscsireject; 62 typedef struct Iscsisnackreq Iscsisnackreq; 63 typedef struct Iscsistate Iscsistate; 64 typedef struct Iscsitaskreq Iscsitaskreq; 65 typedef struct Iscsitaskresp Iscsitaskresp; 66 typedef struct Iscsitextreq Iscsitextreq; 67 typedef struct Iscsitextresp Iscsitextresp; 68 typedef struct Pkt Pkt; 69 typedef struct Pkts Pkts; 70 typedef struct Resppkt Resppkt; 71 72 /* 73 * iscsi on-the-wire packet formats 74 * 75 * all integers are stored big-endian. 76 * common pkt start is bhs, 48 bytes. 77 */ 78 79 /* 80 * first 20 bytes are common *and* defined; another 28 follow but vary. 81 */ 82 #define Iscsibhdr \ 83 uchar op; \ 84 uchar opspfc[3]; \ 85 uchar totahslen; \ 86 uchar dseglen[3]; \ 87 uchar lun[8]; \ 88 uchar itt[4] /* initiator task tag */ 89 90 struct Iscsijustbhdr { 91 Iscsibhdr; 92 }; 93 94 struct Iscsiasynch { 95 Iscsibhdr; 96 97 uchar _pad1[4]; 98 uchar stsseq[4]; 99 uchar expcmdseq[4]; 100 uchar maxcmdseq[4]; 101 102 uchar event; 103 uchar vcode; 104 uchar param1[2]; 105 uchar param2[2]; 106 uchar param3[2]; 107 uchar _pad2[4]; 108 uchar dseg[]; /* dseg[dseglen] */ 109 }; 110 111 112 struct Iscsiloginreq { 113 Iscsibhdr; 114 115 uchar cid[2]; 116 uchar _pad1[2]; 117 uchar cmdseq[4]; 118 uchar expstsseq[4]; 119 120 uchar _pad2[16]; 121 uchar dseg[]; /* dseg[dseglen] */ 122 }; 123 124 struct Iscsiloginresp { 125 Iscsibhdr; 126 127 uchar _pad1[4]; 128 uchar stsseq[4]; 129 uchar expstsseq[4]; 130 uchar maxstsseq[4]; 131 132 uchar stsclass; 133 uchar stsdetail; 134 uchar _pad2[10]; 135 uchar dseg[]; /* dseg[dseglen] */ 136 }; 137 138 139 struct Iscsilogoutreq { 140 Iscsibhdr; 141 142 uchar cid[2]; 143 uchar _pad1[2]; 144 uchar cmdseq[4]; 145 uchar expstsseq[4]; 146 uchar _pad2[16]; 147 }; 148 149 struct Iscsilogoutresp { 150 Iscsibhdr; 151 152 uchar _pad1[4]; 153 uchar stsseq[4]; 154 uchar expcmdseq[4]; 155 uchar maxcmdseq[4]; 156 uchar _pad2[4]; 157 uchar waittime[2]; 158 uchar retaintime[2]; 159 uchar _pad3[4]; 160 }; 161 162 163 struct Iscsinopreq { /* nop-out */ 164 Iscsibhdr; 165 166 uchar ttt[4]; 167 uchar cmdseq[4]; 168 uchar expcmdseq[4]; 169 uchar _pad2[16]; 170 uchar dseg[]; /* dseg[dseglen] */ 171 }; 172 173 struct Iscsinopresp { /* nop-in */ 174 Iscsibhdr; 175 176 uchar ttt[4]; 177 uchar stsseq[4]; 178 uchar expcmdseq[4]; 179 uchar maxcmdseq[4]; 180 uchar _pad2[12]; 181 uchar dseg[]; /* dseg[dseglen] */ 182 }; 183 184 185 struct Iscsiready { 186 Iscsibhdr; 187 188 uchar ttt[4]; 189 uchar stsseq[4]; 190 uchar expcmdseq[4]; 191 uchar r2tseq[4]; 192 uchar bufoff[4]; 193 uchar xferlen[4]; 194 }; 195 196 struct Iscsireject { 197 Iscsibhdr; 198 199 uchar _pad2[4]; 200 uchar stsseq[4]; 201 uchar expcmdseq[4]; 202 uchar maxcmdseq[4]; 203 uchar r2tseq[4]; 204 uchar _pad3[4+4]; 205 uchar dseg[]; /* dseg[dseglen] */ 206 }; 207 208 209 struct Iscsicmdreq { 210 Iscsibhdr; 211 212 uchar expxferlen[4]; 213 uchar cmdseq[4]; 214 uchar expstsseq[4]; 215 216 uchar cdb[16]; 217 uchar dseg[]; /* dseg[dseglen] */ 218 }; 219 220 struct Iscsicmdresp { 221 Iscsibhdr; 222 223 uchar snacktag[4]; 224 uchar stsseq[4]; 225 uchar expcmdseq[4]; 226 uchar maxcmdseq[4]; 227 uchar expdataseq[4]; 228 uchar readresid[4]; 229 uchar resid[4]; 230 uchar dseg[]; /* dseg[dseglen] */ 231 }; 232 233 234 struct Iscsidatain { 235 Iscsibhdr; 236 237 uchar ttt[4]; 238 uchar stsseq[4]; 239 uchar expcmdseq[4]; 240 uchar maxcmdseq[4]; 241 uchar dataseq[4]; 242 uchar buffoff[4]; 243 uchar resid[4]; 244 uchar dseg[]; /* dseg[dseglen] */ 245 }; 246 247 struct Iscsidataout { /* a.k.a. data-out */ 248 Iscsibhdr; 249 250 uchar ttt[4]; 251 uchar _pad1[4]; 252 uchar expstsseq[4]; 253 uchar _pad2[4]; 254 uchar dataseq[4]; 255 uchar buffoff[4]; 256 uchar _pad3[4]; 257 uchar dseg[]; /* dseg[dseglen] */ 258 }; 259 260 261 struct Iscsisnackreq { 262 Iscsibhdr; 263 264 uchar ttt[4]; 265 uchar _pad1[4]; 266 uchar expstsseq[4]; 267 uchar _pad2[8]; 268 uchar begrun[4]; 269 uchar runlen[4]; 270 }; 271 272 273 struct Iscsitaskreq { 274 Iscsibhdr; 275 276 uchar rtt[4]; 277 uchar cmdseq[4]; 278 uchar expstsseq[4]; 279 uchar refcmdseq[4]; 280 uchar expdataseq[4]; 281 uchar _pad1[8]; 282 }; 283 284 struct Iscsitaskresp { 285 Iscsibhdr; 286 287 uchar _pad2[4]; 288 uchar stsseq[4]; 289 uchar expcmdseq[4]; 290 uchar maxcmdseq[4]; 291 uchar _pad4[12]; 292 }; 293 294 295 /* req & resp identical? */ 296 struct Iscsitextreq { 297 Iscsibhdr; 298 299 uchar ttt[4]; 300 uchar cmdseq[4]; 301 uchar expstsseq[4]; 302 uchar _pad1[16]; 303 uchar dseg[]; /* dseg[dseglen] */ 304 }; 305 306 struct Iscsitextresp { 307 Iscsibhdr; 308 309 uchar ttt[4]; 310 uchar cmdseq[4]; 311 uchar expstsseq[4]; 312 uchar _pad1[16]; 313 uchar dseg[]; /* dseg[dseglen] */ 314 }; 315 316 /* 317 * packet-specific data 318 */ 319 struct Pkt { 320 union { 321 Iscsijustbhdr *pkthdr; 322 uchar *pkt; 323 }; 324 uint len; 325 }; 326 struct Resppkt { 327 Iscsicmdresp *resppkt; 328 uint resplen; 329 }; 330 struct Datainpkt { 331 Iscsidatain *datapkt; 332 uint datalen; 333 }; 334 335 /* 336 * a request packet (pkt), its response packet (Resppkt), 337 * and an optional data-in packet for cmd read operations. 338 */ 339 struct Pkts { 340 int op; 341 int immed; 342 ulong totahslen; 343 ulong dseglen; 344 ulong itt; 345 346 Pkt; 347 Datainpkt; 348 Resppkt; 349 }; 350 351 /* 352 * iscsi state, maintained by both parties. 353 * some are per-connection, some per-session. 354 */ 355 struct Iscsistate { 356 ulong cmdseq; /* to be assigned to next command pkt */ 357 ulong expcmdseq; /* next cmd expected by target; previous done */ 358 ulong maxcmdseq; /* maxcmdseq-expcmdseq+1 is target's queue depth */ 359 360 ulong stsseq; 361 ulong expstsseq; /* all previous sts seen */ 362 363 ulong dataseq; 364 ulong r2tseq; 365 366 ulong maxrcvseglen; 367 }; 368