Home | History | Annotate | Line # | Download | only in include
      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 
    122 EXTERN uint32_t iscsi_debug_level;
    123 
    124 /*
    125  * Debugging Functions
    126  */
    127 void	set_debug(const char *);
    128 void	iscsi_trace(const int, const char *, ...)
    129     __printflike(2, 3);
    130 void	iscsi_warn(const char *, const int, const char *, ...)
    131     __printflike(3, 4);
    132 void	iscsi_err(const char *, const int, const char *, ...)
    133     __printflike(3, 4);
    134 void	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
    169 typedef int	socklen_t;
    170 #endif
    171 
    172 /*
    173  * Memory
    174  */
    175 void           *iscsi_malloc(unsigned);
    176 void            iscsi_free(void *);
    177 void           *iscsi_malloc_atomic(unsigned);
    178 void            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 
    192 typedef         pthread_mutex_t iscsi_spin_t;
    193 
    194 int             iscsi_spin_init(iscsi_spin_t * );
    195 int             iscsi_spin_lock(iscsi_spin_t * );
    196 int             iscsi_spin_unlock(iscsi_spin_t * );
    197 int             iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *);
    198 int             iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *);
    199 int             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 
    229 typedef 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 
    237 int             hash_init(hash_t * , int );
    238 int             hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t );
    239 struct initiator_cmd_t *hash_remove(hash_t * , uint32_t );
    240 int             hash_destroy(hash_t * );
    241 
    242 /*
    243  * Queuing
    244  */
    245 
    246 typedef 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 
    255 int             iscsi_queue_init(iscsi_queue_t * , int );
    256 void            iscsi_queue_destroy(iscsi_queue_t * );
    257 int             iscsi_queue_insert(iscsi_queue_t * , void *);
    258 void           *iscsi_queue_remove(iscsi_queue_t * );
    259 int             iscsi_queue_depth(iscsi_queue_t * );
    260 int             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 
    275 int             iscsi_sock_create(int *);
    276 int             iscsi_socks_establish(int *, int *, int *, char *, int);
    277 int		iscsi_waitfor_connection(int *, int, const char *cf, int *);
    278 const char	*iscsi_address_family(int);
    279 int             iscsi_sock_setsockopt(int * , int , int , void *, unsigned);
    280 int             iscsi_sock_getsockopt(int * , int , int , void *, unsigned *);
    281 int             iscsi_sock_bind(int , int);
    282 int             iscsi_sock_listen(int);
    283 int             iscsi_sock_connect(int , char *, int);
    284 int             iscsi_sock_accept(int , int *);
    285 int             iscsi_sock_shutdown(int , int);
    286 int             iscsi_sock_close(int);
    287 int             iscsi_sock_msg(int , int , unsigned , void *, int, int);
    288 int		iscsi_sock_send_header_and_data(int ,
    289 				void *, unsigned ,
    290 				const void *, unsigned , int,
    291 				int, int);
    292 int             iscsi_sock_getsockname(int , struct sockaddr * , unsigned *);
    293 int             iscsi_sock_getpeername(int , struct sockaddr * , unsigned *);
    294 int             modify_iov(struct iovec ** , int *, uint32_t , uint32_t);
    295 
    296 
    297 /*
    298  * Mutexes
    299  */
    300 
    301 typedef pthread_mutex_t iscsi_mutex_t;
    302 
    303 int             iscsi_mutex_init(iscsi_mutex_t *);
    304 int             iscsi_mutex_lock(iscsi_mutex_t *);
    305 int             iscsi_mutex_unlock(iscsi_mutex_t *);
    306 int             iscsi_mutex_destroy(iscsi_mutex_t *);
    307 
    308 #define ISCSI_LOCK(M, ELSE)	do {					\
    309 	if (iscsi_mutex_lock(M) != 0) {					\
    310 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_lock() failed\n");	\
    311 		ELSE;							\
    312 	}								\
    313 } while (/* CONSTCOND */ 0)
    314 
    315 #define ISCSI_UNLOCK(M, ELSE)	do {					\
    316 	if (iscsi_mutex_unlock(M) != 0) {				\
    317 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_unlock() failed\n");	\
    318 		ELSE;							\
    319 	}								\
    320 } while (/* CONSTCOND */ 0)
    321 
    322 #define ISCSI_MUTEX_INIT(M, ELSE) do {					\
    323 	if (iscsi_mutex_init(M) != 0) {					\
    324 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_init() failed\n");	\
    325 		ELSE;							\
    326 	}								\
    327 } while (/* CONSTCOND */ 0)
    328 
    329 #define ISCSI_MUTEX_DESTROY(M, ELSE) do {				\
    330 	if (iscsi_mutex_destroy(M) != 0) {				\
    331 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_destroy() failed\n");	\
    332 		ELSE;							\
    333 	}								\
    334 } while (/* CONSTCOND */ 0)
    335 
    336 /*
    337  * Condition Variable
    338  */
    339 
    340 typedef pthread_cond_t iscsi_cond_t;
    341 
    342 int             iscsi_cond_init(iscsi_cond_t *);
    343 int             iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *);
    344 int             iscsi_cond_signal(iscsi_cond_t *);
    345 int             iscsi_cond_destroy(iscsi_cond_t *);
    346 
    347 #define ISCSI_COND_INIT(C, ELSE) do {					\
    348 	if (iscsi_cond_init(C) != 0) {					\
    349 		ELSE;							\
    350 	}								\
    351 } while (/* CONSTCOND */ 0)
    352 
    353 #define ISCSI_WAIT(C, M, ELSE)	do {					\
    354 	if (iscsi_cond_wait(C, M) != 0) {				\
    355 		ELSE;							\
    356 	}								\
    357 } while (/* CONSTCOND */ 0)
    358 
    359 #define ISCSI_SIGNAL(C, ELSE) 	do {					\
    360 	if (iscsi_cond_signal(C) != 0) {				\
    361 		ELSE;							\
    362 	}								\
    363 } while (/* CONSTCOND */ 0)
    364 
    365 #define ISCSI_COND_DESTROY(C, ELSE)	do {				\
    366 	if (iscsi_cond_destroy(C) != 0) {				\
    367 		ELSE;							\
    368 	}								\
    369 } while (/* CONSTCOND */ 0)
    370 
    371 /*
    372  * Threading Routines
    373  */
    374 
    375 typedef struct iscsi_thread_t {
    376 	pthread_t       pthread;
    377 } iscsi_thread_t;
    378 
    379 int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *);
    380 
    381 #define ISCSI_SET_THREAD(ME)	/* for user pthread id set by pthread_create
    382 				 * in iscsi_thread_create */
    383 #define ISCSI_THREAD_START(NAME)
    384 
    385 /*
    386  * Worker Thread
    387  */
    388 
    389 #define ISCSI_WORKER_STATE_STARTED   1
    390 #define ISCSI_WORKER_STATE_ERROR     2
    391 #define ISCSI_WORKER_STATE_EXITING   4
    392 
    393 typedef struct {
    394 	iscsi_thread_t  thread;
    395 	iscsi_mutex_t   work_mutex;
    396 	iscsi_cond_t    work_cond;
    397 	iscsi_mutex_t   exit_mutex;
    398 	iscsi_cond_t    exit_cond;
    399 	int             id;
    400 	int             pid;
    401 	volatile uint32_t state;
    402 }               iscsi_worker_t;
    403 
    404 #define ISCSI_WORKER_EXIT(ME) do {					\
    405 	iscsi_trace(TRACE_ISCSI_DEBUG, "%s:%d: %s", __FILE__, __LINE__, "exiting\n");\
    406 	(ME)->state |= ISCSI_WORKER_STATE_EXITING;			\
    407 	return 0;							\
    408 	/* NOTREACHED */						\
    409 } while (/* CONSTCOND */ 0)
    410 
    411 /*
    412  * Spin Lock
    413  */
    414 #define ISCSI_SPIN
    415 
    416 /*
    417  * Pre/Post condition checking
    418  */
    419 
    420 #define NO_CLEANUP {}
    421 
    422 #if 0
    423 #define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC)                       \
    424 if ((V1)!=(V2)) {                                                    \
    425   iscsi_err(__FILE__, __LINE__, "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2);    \
    426   CU;                                                                \
    427   return RC;                                                         \
    428 }
    429 #endif
    430 
    431 #if 0
    432 #define ERROR_NOT_EQUAL(NAME, V1, V2, CU) 	do {			\
    433 	if ((V1)!=(V2)) {						\
    434 		iscsi_err(__FILE__, __LINE__,			\
    435 			"Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
    436 		CU;							\
    437 	}								\
    438 } while(/* CONSTCOND */0)
    439 #endif
    440 
    441 /*
    442  * Misc. Functions
    443  */
    444 
    445 uint32_t iscsi_atoi(char *);
    446 int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t);
    447 int HexDataToText(uint8_t *, uint32_t , char *, uint32_t);
    448 void GenRandomData(uint8_t *, uint32_t);
    449 uint32_t gen_digest(const void *, int, uint32_t);
    450 
    451 
    452 /* this is the maximum number of iovecs which we can use in
    453 * iscsi_sock_send_header_and_data */
    454 #ifndef ISCSI_MAX_IOVECS
    455 #define ISCSI_MAX_IOVECS        32
    456 #endif
    457 
    458 enum {
    459 	/* used in iscsi_sock_msg() */
    460 	Receive = 0,
    461 	Transmit = 1
    462 };
    463 
    464 int		allow_netmask(const char *, const char *);
    465 
    466 #endif /* _ISCSIUTIL_H_ */
    467