1/* 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 3 * By downloading, copying, installing or using the software you agree 4 * to this license. If you do not agree to this license, do not 5 * download, install, copy or use the software. 6 * 7 * Intel License Agreement 8 * 9 * Copyright (c) 2000, Intel Corporation 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * -Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * -Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the 22 * distribution. 23 * 24 * -The name of Intel Corporation may not be used to endorse or 25 * promote products derived from this software without specific prior 26 * written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL 32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 37 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 38 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 */ 41#ifndef _ISCSIUTIL_H_ 42#define _ISCSIUTIL_H_ 43 44#include "config.h" 45 46#include <sys/param.h> /* MIN/MAX */ 47#include <stdio.h> 48#include <stdlib.h> 49 50#ifdef HAVE_STDINT_H 51#include <stdint.h> 52#endif 53 54#ifdef HAVE_STRING_H 55#include <string.h> 56#endif 57 58#ifdef HAVE_PTHREAD_H 59#include <pthread.h> 60#endif 61 62#ifdef HAVE_UNISTD_H 63#include <unistd.h> 64#endif 65 66#ifdef HAVE_SYS_UIO_H 67#include <sys/uio.h> 68#endif 69 70#ifdef HAVE_SYS_SOCKET_H 71#include <sys/socket.h> 72#endif 73 74#ifdef HAVE_FCNTL_H 75#include <fcntl.h> 76#endif 77 78#ifdef HAVE_SYSLOG_H 79#include <syslog.h> 80#endif 81 82/* 83 * Debugging Levels 84 */ 85 86#define TRACE_NET_DEBUG 0x00000001 87#define TRACE_NET_BUFF 0x00000002 88#define TRACE_NET_IOV 0x00000004 89#define TRACE_NET_ALL (TRACE_NET_DEBUG|TRACE_NET_BUFF|TRACE_NET_IOV) 90 91#define TRACE_ISCSI_DEBUG 0x00000010 92#define TRACE_ISCSI_CMD 0x00000020 93#define TRACE_ISCSI_ARGS 0x00000040 94#define TRACE_ISCSI_PARAM 0x00000080 95#define TRACE_ISCSI_ALL (TRACE_ISCSI_DEBUG|TRACE_ISCSI_ARGS|TRACE_ISCSI_PARAM|TRACE_ISCSI_CMD) 96 97#define TRACE_SCSI_DEBUG 0x00000100 98#define TRACE_SCSI_CMD 0x00000200 99#define TRACE_SCSI_DATA 0x00000400 100#define TRACE_SCSI_ARGS 0x00000800 101#define TRACE_SCSI_ALL (TRACE_SCSI_DEBUG|TRACE_SCSI_CMD|TRACE_SCSI_DATA|TRACE_SCSI_ARGS) 102 103#define TRACE_DEBUG 0x00001000 104#define TRACE_HASH 0x00002000 105#define TRACE_SYNC 0x00004000 106#define TRACE_QUEUE 0x00008000 107#define TRACE_WARN 0x00010000 108#define TRACE_MEM 0x00020000 109 110#define TRACE_OSD 0x00040000 111#define TRACE_OSDFS 0x00080000 112#define TRACE_OSDSO 0x00100000 113#define TRACE_ALL 0xffffffff 114 115/* 116 * Set debugging level here. Turn on debugging in Makefile. 117 */ 118#ifndef EXTERN 119#define EXTERN extern 120#endif 121 122EXTERN uint32_t iscsi_debug_level; 123 124/* 125 * Debugging Functions 126 */ 127void set_debug(const char *); 128void iscsi_trace(const int, const char *, ...) 129 __printflike(2, 3); 130void iscsi_warn(const char *, const int, const char *, ...) 131 __printflike(3, 4); 132void iscsi_err(const char *, const int, const char *, ...) 133 __printflike(3, 4); 134void iscsi_print_buffer(const char *, const size_t); 135 136 137/* 138 * Byte Order 139 */ 140 141#ifdef HAVE_ASM_BYTEORDER_H 142#include <asm/byteorder.h> 143#endif 144 145#ifdef HAVE_SYS_BYTEORDER_H 146#include <sys/byteorder.h> 147#endif 148 149#ifdef HAVE_BYTESWAP_H 150#include <byteswap.h> 151#endif 152 153#ifdef HAVE_MACHINE_ENDIAN_H 154#include <machine/endian.h> 155#endif 156 157#define __BYTE_ORDER _BYTE_ORDER 158#define __BIG_ENDIAN _BIG_ENDIAN 159#define __LITTLE_ENDIAN _LITTLE_ENDIAN 160 161#define ISCSI_NTOHLL(a) ISCSI_BE64TOH(a) 162#define ISCSI_HTONLL(a) ISCSI_HTOBE64(a) 163#define ISCSI_NTOHL(a) ntohl(a) 164#define ISCSI_HTONL(a) htonl(a) 165#define ISCSI_NTOHS(a) ntohs(a) 166#define ISCSI_HTONS(a) htons(a) 167 168#ifndef HAVE_SOCKLEN_T 169typedef int socklen_t; 170#endif 171 172/* 173 * Memory 174 */ 175void *iscsi_malloc(unsigned); 176void iscsi_free(void *); 177void *iscsi_malloc_atomic(unsigned); 178void iscsi_free_atomic(void *); 179 180/* 181 * Comparison 182 */ 183 184#ifndef MIN 185#define MIN(A,B) (((A)<(B))?(A):(B)) 186#endif 187 188#define MIN_3(A,B,C) (((A)<(B))?(((A)<(C))?(A):(C)):(((B)<(C))?(B):(C))) 189 190/* Spin locks */ 191 192typedef pthread_mutex_t iscsi_spin_t; 193 194int iscsi_spin_init(iscsi_spin_t * ); 195int iscsi_spin_lock(iscsi_spin_t * ); 196int iscsi_spin_unlock(iscsi_spin_t * ); 197int iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *); 198int iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *); 199int iscsi_spin_destroy(iscsi_spin_t * ); 200 201/* 202 * End of ISCSI spin routines 203 */ 204 205/* 206 * Tags 207 */ 208 209#define ISCSI_SET_TAG(tag) do { \ 210 iscsi_spin_lock(&g_tag_spin); \ 211 *tag = g_tag++; \ 212 iscsi_spin_unlock(&g_tag_spin); \ 213} while (/* CONSTCOND */ 0) 214 215#define ISCSI_SET_TAG_IN_INTR(tag) do { \ 216 uint32_t flags; \ 217 iscsi_spin_lock_irqsave(&g_tag_spin, &flags); \ 218 *tag = g_tag++; \ 219 iscsi_spin_unlock_irqrestore(&g_tag_spin, &flags); \ 220} while (/* CONSTCOND */ 0) 221 222 223 224/* 225 * Hashing 226 */ 227 228 229typedef struct hash_t { 230 struct initiator_cmd_t **bucket; 231 int collisions; 232 int insertions; 233 int n; 234 iscsi_spin_t lock; 235} hash_t; 236 237int hash_init(hash_t * , int ); 238int hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t ); 239struct initiator_cmd_t *hash_remove(hash_t * , uint32_t ); 240int hash_destroy(hash_t * ); 241 242/* 243 * Queuing 244 */ 245 246typedef struct iscsi_queue_t { 247 int head; 248 int tail; 249 int count; 250 void **elem; 251 int depth; 252 iscsi_spin_t lock; 253} iscsi_queue_t; 254 255int iscsi_queue_init(iscsi_queue_t * , int ); 256void iscsi_queue_destroy(iscsi_queue_t * ); 257int iscsi_queue_insert(iscsi_queue_t * , void *); 258void *iscsi_queue_remove(iscsi_queue_t * ); 259int iscsi_queue_depth(iscsi_queue_t * ); 260int iscsi_queue_full(iscsi_queue_t * ); 261 262/* 263 * Socket Abstraction 264 */ 265 266/* Turning off Nagle's Algorithm doesn't always seem to work, */ 267/* so we combine two messages into one when the second's size */ 268/* is less than or equal to ISCSI_SOCK_HACK_CROSSOVER. */ 269 270#define ISCSI_SOCK_HACK_CROSSOVER 1024 271#define ISCSI_SOCK_CONNECT_NONBLOCK 0 272#define ISCSI_SOCK_CONNECT_TIMEOUT 1 273#define ISCSI_SOCK_MSG_BYTE_ALIGN 4 274 275int iscsi_sock_create(int *); 276int iscsi_socks_establish(int *, int *, int *, char *, int); 277int iscsi_waitfor_connection(int *, int, const char *cf, int *); 278const char *iscsi_address_family(int); 279int iscsi_sock_setsockopt(int * , int , int , void *, unsigned); 280int iscsi_sock_getsockopt(int * , int , int , void *, unsigned *); 281int iscsi_sock_bind(int , int); 282int iscsi_sock_listen(int); 283int iscsi_sock_connect(int , char *, int); 284int iscsi_sock_accept(int , int *); 285int iscsi_sock_shutdown(int , int); 286int iscsi_sock_close(int); 287int iscsi_sock_msg(int , int , unsigned , void *, int); 288int iscsi_sock_send_header_and_data(int , 289 void *, unsigned , 290 const void *, unsigned , int); 291int iscsi_sock_getsockname(int , struct sockaddr * , unsigned *); 292int iscsi_sock_getpeername(int , struct sockaddr * , unsigned *); 293int modify_iov(struct iovec ** , int *, uint32_t , uint32_t); 294 295 296/* 297 * Mutexes 298 */ 299 300typedef pthread_mutex_t iscsi_mutex_t; 301 302int iscsi_mutex_init(iscsi_mutex_t *); 303int iscsi_mutex_lock(iscsi_mutex_t *); 304int iscsi_mutex_unlock(iscsi_mutex_t *); 305int iscsi_mutex_destroy(iscsi_mutex_t *); 306 307#define ISCSI_LOCK(M, ELSE) do { \ 308 if (iscsi_mutex_lock(M) != 0) { \ 309 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_lock() failed\n"); \ 310 ELSE; \ 311 } \ 312} while (/* CONSTCOND */ 0) 313 314#define ISCSI_UNLOCK(M, ELSE) do { \ 315 if (iscsi_mutex_unlock(M) != 0) { \ 316 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_unlock() failed\n"); \ 317 ELSE; \ 318 } \ 319} while (/* CONSTCOND */ 0) 320 321#define ISCSI_MUTEX_INIT(M, ELSE) do { \ 322 if (iscsi_mutex_init(M) != 0) { \ 323 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_init() failed\n"); \ 324 ELSE; \ 325 } \ 326} while (/* CONSTCOND */ 0) 327 328#define ISCSI_MUTEX_DESTROY(M, ELSE) do { \ 329 if (iscsi_mutex_destroy(M) != 0) { \ 330 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_destroy() failed\n"); \ 331 ELSE; \ 332 } \ 333} while (/* CONSTCOND */ 0) 334 335/* 336 * Condition Variable 337 */ 338 339typedef pthread_cond_t iscsi_cond_t; 340 341int iscsi_cond_init(iscsi_cond_t *); 342int iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *); 343int iscsi_cond_signal(iscsi_cond_t *); 344int iscsi_cond_destroy(iscsi_cond_t *); 345 346#define ISCSI_COND_INIT(C, ELSE) do { \ 347 if (iscsi_cond_init(C) != 0) { \ 348 ELSE; \ 349 } \ 350} while (/* CONSTCOND */ 0) 351 352#define ISCSI_WAIT(C, M, ELSE) do { \ 353 if (iscsi_cond_wait(C, M) != 0) { \ 354 ELSE; \ 355 } \ 356} while (/* CONSTCOND */ 0) 357 358#define ISCSI_SIGNAL(C, ELSE) do { \ 359 if (iscsi_cond_signal(C) != 0) { \ 360 ELSE; \ 361 } \ 362} while (/* CONSTCOND */ 0) 363 364#define ISCSI_COND_DESTROY(C, ELSE) do { \ 365 if (iscsi_cond_destroy(C) != 0) { \ 366 ELSE; \ 367 } \ 368} while (/* CONSTCOND */ 0) 369 370/* 371 * Threading Routines 372 */ 373 374typedef struct iscsi_thread_t { 375 pthread_t pthread; 376} iscsi_thread_t; 377 378int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *); 379 380#define ISCSI_SET_THREAD(ME) /* for user pthread id set by pthread_create 381 * in iscsi_thread_create */ 382#define ISCSI_THREAD_START(NAME) 383 384/* 385 * Worker Thread 386 */ 387 388#define ISCSI_WORKER_STATE_STARTED 1 389#define ISCSI_WORKER_STATE_ERROR 2 390#define ISCSI_WORKER_STATE_EXITING 4 391 392typedef struct { 393 iscsi_thread_t thread; 394 iscsi_mutex_t work_mutex; 395 iscsi_cond_t work_cond; 396 iscsi_mutex_t exit_mutex; 397 iscsi_cond_t exit_cond; 398 int id; 399 int pid; 400 volatile uint32_t state; 401} iscsi_worker_t; 402 403#define ISCSI_WORKER_EXIT(ME) do { \ 404 iscsi_trace(TRACE_ISCSI_DEBUG, "%s:%d: %s", __FILE__, __LINE__, "exiting\n");\ 405 (ME)->state |= ISCSI_WORKER_STATE_EXITING; \ 406 return 0; \ 407 /* NOTREACHED */ \ 408} while (/* CONSTCOND */ 0) 409 410/* 411 * Spin Lock 412 */ 413#define ISCSI_SPIN 414 415/* 416 * Pre/Post condition checking 417 */ 418 419#define NO_CLEANUP {} 420 421#if 0 422#define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC) \ 423if ((V1)!=(V2)) { \ 424 iscsi_err(__FILE__, __LINE__, "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \ 425 CU; \ 426 return RC; \ 427} 428#endif 429 430#if 0 431#define ERROR_NOT_EQUAL(NAME, V1, V2, CU) do { \ 432 if ((V1)!=(V2)) { \ 433 iscsi_err(__FILE__, __LINE__, \ 434 "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \ 435 CU; \ 436 } \ 437} while(/* CONSTCOND */0) 438#endif 439 440/* 441 * Misc. Functions 442 */ 443 444uint32_t iscsi_atoi(char *); 445int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t); 446int HexDataToText(uint8_t *, uint32_t , char *, uint32_t); 447void GenRandomData(uint8_t *, uint32_t); 448 449/* this is the maximum number of iovecs which we can use in 450* iscsi_sock_send_header_and_data */ 451#ifndef ISCSI_MAX_IOVECS 452#define ISCSI_MAX_IOVECS 32 453#endif 454 455enum { 456 /* used in iscsi_sock_msg() */ 457 Receive = 0, 458 Transmit = 1 459}; 460 461int allow_netmask(const char *, const char *); 462 463#endif /* _ISCSIUTIL_H_ */ 464