1 /* 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or 3 * using the software you agree to this license. If you do not agree to this license, do not download, install, 4 * copy or use the software. 5 * 6 * Intel License Agreement 7 * 8 * Copyright (c) 2002, Intel Corporation 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that 12 * the following conditions are met: 13 * 14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the 15 * following disclaimer. 16 * 17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 18 * following disclaimer in the documentation and/or other materials provided with the distribution. 19 * 20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Transport-independent Methods 35 */ 36 #include "config.h" 37 38 39 #include "osd.h" 40 #include "iscsiutil.h" 41 #include "compat.h" 42 #include "osd_ops.h" 43 44 #ifdef HAVE_NETINET_IN_H 45 #include <netinet/in.h> 46 #endif 47 48 static int 49 extract_attribute(uint32_t page, uint32_t n, uint16_t len, 50 uint8_t * data, unsigned length, void *val) 51 { 52 int i = 0; 53 54 for (i = 0; i < length;) { 55 if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != page) { 56 iscsi_err(__FILE__, __LINE__, "page mismatch: got 0x%x, expected 0x%x\n", ISCSI_NTOHL(*(uint32_t *) (data + i)), page); 57 return -1; 58 } 59 i += 4; 60 if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != n) { 61 iscsi_err(__FILE__, __LINE__, "index mismatch\n"); 62 return -1; 63 } 64 i += 4; 65 if (ISCSI_NTOHS(*(uint16_t *) (data + i)) != len) { 66 iscsi_err(__FILE__, __LINE__, "len mismatch\n"); 67 return -1; 68 } 69 i += 2; 70 iscsi_trace(TRACE_DEBUG, "page 0x%x, index %u, len %u\n", page, n, len); 71 memcpy(val, data + i, len); 72 i += len; 73 } 74 iscsi_trace(TRACE_DEBUG, "parsed %i bytes\n", i); 75 return i; 76 } 77 78 79 int 80 osd_create_group(void *dev, 81 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem), 82 uint32_t * GroupID) 83 { 84 osd_args_t args; 85 #if 0 86 uint8_t get_list[8]; 87 #endif 88 uint8_t get_data[14]; 89 OSD_OPS_MEM mem; 90 91 mem.recv_data = get_data; 92 mem.recv_len = 14; 93 mem.recv_sg = 0; 94 95 memset(&args, 0, sizeof(osd_args_t)); 96 args.opcode = 0x7F; 97 args.service_action = OSD_CREATE_GROUP; 98 99 #if 0 100 args.length = 8; 101 args.get_attributes_list_length = 8; 102 *((unsigned long *) get_list) = ISCSI_HTONL(0x40000001); 103 *((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x1); 104 mem.send_data = get_list; 105 mem.send_len = 8; 106 mem.send_sg = 0; 107 #else 108 args.get_attributes_page = 0x40000001; 109 mem.send_data = NULL; 110 mem.send_len = 0; 111 mem.send_sg = 0; 112 #endif 113 114 args.get_attributes_allocation_length = 14; 115 if (osd_exec(dev, &args, &mem) != 0) { 116 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 117 return -1; 118 } 119 if (extract_attribute(0x40000001, 0x1, 4, get_data, 14, GroupID) == -1) { 120 iscsi_err(__FILE__, __LINE__, "extract_attributes() failed\n"); 121 return -1; 122 } 123 *GroupID = ISCSI_NTOHL(*GroupID); 124 iscsi_trace(TRACE_OSD, "osd_create_group() OK --> GroupID 0x%x\n", *GroupID); 125 126 return 0; 127 } 128 129 int 130 osd_create(void *dev, uint32_t GroupID, 131 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem), 132 uint64_t * UserID) 133 { 134 osd_args_t args; 135 #if 0 136 uint8_t get_list[8]; 137 #endif 138 uint8_t get_data[18]; 139 OSD_OPS_MEM mem; 140 141 mem.recv_data = get_data; 142 mem.recv_len = 18; 143 mem.recv_sg = 0; 144 145 memset(&args, 0, sizeof(osd_args_t)); 146 args.opcode = 0x7F; 147 args.service_action = OSD_CREATE; 148 args.GroupID = GroupID; 149 150 #if 0 151 args.length = 8; 152 args.get_attributes_list_length = 8; 153 *((unsigned long *) get_list) = ISCSI_HTONL(0x00000001); 154 *((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x2); 155 mem.send_data = get_list; 156 mem.send_len = 8; 157 mem.send_sg = 0; 158 #else 159 args.get_attributes_page = 0x000000001; 160 mem.send_data = NULL; 161 mem.send_len = 0; 162 mem.send_sg = 0; 163 #endif 164 165 args.get_attributes_allocation_length = 18; 166 if (osd_exec(dev, &args, &mem) != 0) { 167 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 168 return -1; 169 } 170 if (extract_attribute(0x00000001, 0x2, 8, get_data, 18, UserID) == -1) { 171 iscsi_err(__FILE__, __LINE__, "extract_attributes() failed\n"); 172 return -1; 173 } 174 *UserID = ISCSI_NTOHLL(*UserID); 175 iscsi_trace(TRACE_OSD, "osd_create(GroupID 0x%x) OK --> UserID 0x%llx\n", GroupID, *UserID); 176 177 return 0; 178 } 179 180 int 181 osd_remove_group(void *dev, uint32_t GroupID, 182 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem)) 183 { 184 osd_args_t args; 185 OSD_OPS_MEM mem; 186 187 mem.send_data = NULL; 188 mem.send_len = 0; 189 mem.send_sg = 0; 190 mem.recv_data = NULL; 191 mem.recv_len = 0; 192 mem.recv_sg = 0; 193 194 memset(&args, 0, sizeof(osd_args_t)); 195 args.opcode = 0x7F; 196 args.service_action = OSD_REMOVE_GROUP; 197 args.GroupID = GroupID; 198 if (osd_exec(dev, &args, &mem) != 0) { 199 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 200 return -1; 201 } 202 iscsi_trace(TRACE_OSD, "osd_remove_group(Group ID 0x%x) OK\n", GroupID); 203 204 return 0; 205 } 206 207 int 208 osd_remove(void *dev, uint32_t GroupID, uint64_t UserID, 209 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem)) 210 { 211 osd_args_t args; 212 OSD_OPS_MEM mem; 213 214 mem.send_data = NULL; 215 mem.send_len = 0; 216 mem.send_sg = 0; 217 mem.recv_data = NULL; 218 mem.recv_len = 0; 219 mem.recv_sg = 0; 220 221 memset(&args, 0, sizeof(osd_args_t)); 222 args.opcode = 0x7F; 223 args.service_action = OSD_REMOVE; 224 args.UserID = UserID; 225 args.GroupID = GroupID; 226 if (osd_exec(dev, &args, &mem) != 0) { 227 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 228 return -1; 229 } 230 iscsi_trace(TRACE_OSD, "osd_remove(GroupID 0x%x, UserID 0x%llx) OK\n", GroupID, UserID); 231 232 return 0; 233 } 234 235 int 236 osd_write(void *dev, 237 uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, const void *send_data, int sg_len, 238 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem)) 239 { 240 osd_args_t args; 241 OSD_OPS_MEM mem; 242 243 iscsi_trace(TRACE_OSD, "osd_write(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len); 244 mem.send_data = send_data; 245 mem.send_len = len; 246 mem.send_sg = sg_len; 247 mem.recv_data = NULL; 248 mem.recv_len = 0; 249 mem.recv_sg = 0; 250 memset(&args, 0, sizeof(osd_args_t)); 251 args.opcode = 0x7F; 252 args.service_action = OSD_WRITE; 253 args.GroupID = GroupID; 254 args.UserID = UserID; 255 args.offset = offset; 256 args.length = len; 257 if (osd_exec(dev, &args, &mem) != 0) { 258 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 259 return -1; 260 } 261 return 0; 262 } 263 264 int 265 osd_read(void *dev, 266 uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, void *recv_data, int sg_len, 267 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem)) 268 { 269 osd_args_t args; 270 OSD_OPS_MEM mem; 271 272 iscsi_trace(TRACE_OSD, "osd_read(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len); 273 mem.send_data = NULL; 274 mem.send_len = 0; 275 mem.send_sg = 0; 276 mem.recv_data = recv_data; 277 mem.recv_len = len; 278 mem.recv_sg = sg_len; 279 memset(&args, 0, sizeof(osd_args_t)); 280 args.opcode = 0x7F; 281 args.service_action = OSD_READ; 282 args.GroupID = GroupID; 283 args.UserID = UserID; 284 args.offset = offset; 285 args.length = len; 286 if (osd_exec(dev, &args, &mem) != 0) { 287 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 288 return -1; 289 } 290 return 0; 291 } 292 293 int 294 osd_set_one_attr(void *dev, 295 uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t len, void *value, 296 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem)) 297 { 298 osd_args_t args; 299 OSD_OPS_MEM mem; 300 uint8_t list[10]; 301 #if 0 302 struct iovec sg[2]; 303 #else 304 uint8_t *buffer = NULL; 305 #endif 306 307 iscsi_trace(TRACE_OSD, "osd_set_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Len %u)\n", 308 GroupID, UserID, page, n, len); 309 memset(&args, 0, sizeof(osd_args_t)); 310 args.opcode = 0x7F; 311 args.service_action = OSD_SET_ATTR; 312 args.GroupID = GroupID; 313 args.UserID = UserID; 314 args.length = 10 + len; 315 args.set_attributes_list_length = 10 + len; 316 *((uint32_t *) (list + 0)) = ISCSI_HTONL(page); 317 *((uint32_t *) (list + 4)) = ISCSI_HTONL(n); 318 *((uint16_t *) (list + 8)) = ISCSI_HTONS(len); 319 #if 0 320 sg[0].iov_base = list; 321 sg[0].iov_len = 10; 322 sg[1].iov_base = value; 323 sg[1].iov_len = len; 324 mem.send_data = sg; 325 mem.send_len = 10 + len; 326 mem.send_sg = 2; 327 #else 328 if ((buffer = iscsi_malloc_atomic(10 + len)) == NULL) { 329 iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 330 return -1; 331 } 332 memcpy(buffer, list, 10); 333 memcpy(buffer + 10, value, len); 334 mem.send_data = buffer; 335 mem.send_len = 10 + len; 336 mem.send_sg = 0; 337 #endif 338 mem.recv_data = NULL; 339 mem.recv_len = 0; 340 mem.recv_sg = 0; 341 342 if (osd_exec(dev, &args, &mem) != 0) { 343 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 344 return -1; 345 } 346 if (buffer) 347 iscsi_free_atomic(buffer); 348 349 return 0; 350 } 351 352 int 353 osd_get_one_attr(void *dev, 354 uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t alloc_len, 355 int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem), 356 uint16_t * len, void *value) 357 { 358 osd_args_t args; 359 OSD_OPS_MEM mem; 360 uint8_t list_out[8]; 361 #if 0 362 uint8_t list_in[10]; 363 struct iovec sg[2]; 364 #else 365 uint8_t *buffer; 366 #endif 367 368 iscsi_trace(TRACE_OSD, "osd_get_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Alloc Len %u)\n", 369 GroupID, UserID, page, n, alloc_len); 370 memset(&args, 0, sizeof(osd_args_t)); 371 args.opcode = 0x7F; 372 args.service_action = OSD_GET_ATTR; 373 args.GroupID = GroupID; 374 args.UserID = UserID; 375 if (n) { 376 args.length = 8; 377 *((uint32_t *) (list_out + 0)) = ISCSI_HTONL(page); 378 *((uint32_t *) (list_out + 4)) = ISCSI_HTONL(n); 379 args.get_attributes_list_length = 8; 380 mem.send_data = list_out; 381 mem.send_len = 8; 382 mem.send_sg = 0; 383 } else { 384 iscsi_trace(TRACE_OSD, "requesting entire page or reference page\n"); 385 mem.send_data = NULL; 386 mem.send_len = 0; 387 mem.send_sg = 0; 388 args.get_attributes_page = page; 389 } 390 #if 0 391 sg[0].iov_base = list_in; 392 sg[0].iov_len = 10; 393 sg[1].iov_base = value; 394 sg[1].iov_len = alloc_len; 395 mem.recv_data = sg; 396 mem.recv_len = 10 + alloc_len; 397 mem.recv_sg = 2; 398 #else 399 if ((buffer = iscsi_malloc_atomic(10 + alloc_len)) == NULL) { 400 iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 401 return -1; 402 } 403 mem.recv_data = buffer; 404 mem.recv_len = 10 + alloc_len; 405 mem.recv_sg = 0; 406 #endif 407 args.get_attributes_allocation_length = 10 + alloc_len; 408 if (osd_exec(dev, &args, &mem) != 0) { 409 iscsi_err(__FILE__, __LINE__, "osd_exec() failed\n"); 410 return -1; 411 } 412 memcpy(value, buffer + 10, alloc_len); 413 if (buffer) 414 iscsi_free_atomic(buffer); 415 return 0; 416 } 417