xref: /netbsd-src/external/bsd/iscsi/dist/include/iscsiutil.h (revision 0953dc8744b62dfdecb2f203329e730593755659)
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 <stdio.h>
47 #include <stdlib.h>
48 
49 #ifdef HAVE_STDINT_H
50 #include <stdint.h>
51 #endif
52 
53 #ifdef HAVE_STRING_H
54 #include <string.h>
55 #endif
56 
57 #ifdef HAVE_PTHREAD_H
58 #include <pthread.h>
59 #endif
60 
61 #ifdef HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64 
65 #ifdef HAVE_SYS_UIO_H
66 #include <sys/uio.h>
67 #endif
68 
69 #ifdef HAVE_SYS_SOCKET_H
70 #include <sys/socket.h>
71 #endif
72 
73 #ifdef HAVE_FCNTL_H
74 #include <fcntl.h>
75 #endif
76 
77 #ifdef HAVE_SYSLOG_H
78 #include <syslog.h>
79 #endif
80 
81 /*
82  *
83  */
84 
85 #define ISCSI_HTONLL6(x) (uint64_t) \
86       ( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40))     \
87       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24))     \
88       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8))      \
89       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8))      \
90       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24))     \
91       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40)))
92 
93 #define ISCSI_NTOHLL6(x) (uint64_t) \
94       ( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40))     \
95       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24))     \
96       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8))      \
97       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8))      \
98       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24))     \
99       | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40)))
100 
101 /*
102  * Debugging Levels
103  */
104 
105 #define TRACE_NET_DEBUG      0x00000001
106 #define TRACE_NET_BUFF       0x00000002
107 #define TRACE_NET_IOV        0x00000004
108 #define TRACE_NET_ALL        (TRACE_NET_DEBUG|TRACE_NET_BUFF|TRACE_NET_IOV)
109 
110 #define TRACE_ISCSI_DEBUG    0x00000010
111 #define TRACE_ISCSI_CMD      0x00000020
112 #define TRACE_ISCSI_ARGS     0x00000040
113 #define TRACE_ISCSI_PARAM    0x00000080
114 #define TRACE_ISCSI_ALL      (TRACE_ISCSI_DEBUG|TRACE_ISCSI_ARGS|TRACE_ISCSI_PARAM|TRACE_ISCSI_CMD)
115 
116 #define TRACE_SCSI_DEBUG     0x00000100
117 #define TRACE_SCSI_CMD       0x00000200
118 #define TRACE_SCSI_DATA      0x00000400
119 #define TRACE_SCSI_ARGS      0x00000800
120 #define TRACE_SCSI_ALL       (TRACE_SCSI_DEBUG|TRACE_SCSI_CMD|TRACE_SCSI_DATA|TRACE_SCSI_ARGS)
121 
122 #define TRACE_DEBUG          0x00001000
123 #define TRACE_HASH           0x00002000
124 #define TRACE_SYNC           0x00004000
125 #define TRACE_QUEUE          0x00008000
126 #define TRACE_WARN           0x00010000
127 #define TRACE_MEM            0x00020000
128 
129 #define TRACE_OSD            0x00040000
130 #define TRACE_OSDFS          0x00080000
131 #define TRACE_OSDSO          0x00100000
132 #define TRACE_ALL            0xffffffff
133 
134 /*
135  * Set debugging level here. Turn on debugging in Makefile.
136   */
137 #ifndef EXTERN
138 #define EXTERN  extern
139 #endif
140 
141 EXTERN uint32_t iscsi_debug_level;
142 
143 /*
144  * Debugging Functions
145  */
146 void	set_debug(const char *);
147 void	iscsi_trace(const int, const char *, ...)
148     __printflike(2, 3);
149 void	iscsi_warn(const char *, const int, const char *, ...)
150     __printflike(3, 4);
151 void	iscsi_err(const char *, const int, const char *, ...)
152     __printflike(3, 4);
153 void	iscsi_print_buffer(const char *, const size_t);
154 
155 
156 /*
157  * Byte Order
158   */
159 
160 #ifdef HAVE_ASM_BYTEORDER_H
161 #include <asm/byteorder.h>
162 #endif
163 
164 #ifdef HAVE_SYS_BYTEORDER_H
165 #include <sys/byteorder.h>
166 #endif
167 
168 #ifdef HAVE_BYTESWAP_H
169 #include <byteswap.h>
170 #endif
171 
172 #ifdef HAVE_MACHINE_ENDIAN_H
173 #include <machine/endian.h>
174 #endif
175 
176 #define __BYTE_ORDER    _BYTE_ORDER
177 #define __BIG_ENDIAN    _BIG_ENDIAN
178 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
179 
180 #define ISCSI_NTOHLL(a)	ISCSI_BE64TOH(a)
181 #define ISCSI_HTONLL(a)	ISCSI_HTOBE64(a)
182 #define ISCSI_NTOHL(a)	ntohl(a)
183 #define ISCSI_HTONL(a)	htonl(a)
184 #define ISCSI_NTOHS(a)	ntohs(a)
185 #define ISCSI_HTONS(a)	htons(a)
186 
187 #ifndef HAVE_SOCKLEN_T
188 typedef int	socklen_t;
189 #endif
190 
191 /*
192  * Memory
193  */
194 void           *iscsi_malloc(unsigned);
195 void            iscsi_free(void *);
196 void           *iscsi_malloc_atomic(unsigned);
197 void            iscsi_free_atomic(void *);
198 
199 /*
200  * Comparison
201  */
202 
203 #ifndef MIN
204 #define MIN(A,B) (((A)<(B))?(A):(B))
205 #endif
206 
207 #define MIN_3(A,B,C) (((A)<(B))?(((A)<(C))?(A):(C)):(((B)<(C))?(B):(C)))
208 
209 /* Spin locks */
210 
211 typedef         pthread_mutex_t iscsi_spin_t;
212 
213 int             iscsi_spin_init(iscsi_spin_t * );
214 int             iscsi_spin_lock(iscsi_spin_t * );
215 int             iscsi_spin_unlock(iscsi_spin_t * );
216 int             iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *);
217 int             iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *);
218 int             iscsi_spin_destroy(iscsi_spin_t * );
219 
220 /*
221  * End of ISCSI spin routines
222  */
223 
224 /*
225  * Tags
226  */
227 
228 #define ISCSI_SET_TAG(tag) do {						\
229 	iscsi_spin_lock(&g_tag_spin);					\
230 	*tag = g_tag++;							\
231 	iscsi_spin_unlock(&g_tag_spin);					\
232 } while (/* CONSTCOND */ 0)
233 
234 #define ISCSI_SET_TAG_IN_INTR(tag) do {					\
235 	uint32_t flags;							\
236 	iscsi_spin_lock_irqsave(&g_tag_spin, &flags);			\
237 	*tag = g_tag++;							\
238 	iscsi_spin_unlock_irqrestore(&g_tag_spin, &flags);		\
239 } while (/* CONSTCOND */ 0)
240 
241 
242 
243 /*
244  * Hashing
245  */
246 
247 
248 typedef struct hash_t {
249 	struct initiator_cmd_t **bucket;
250 	int             collisions;
251 	int             insertions;
252 	int             n;
253 	iscsi_spin_t    lock;
254 } hash_t;
255 
256 int             hash_init(hash_t * , int );
257 int             hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t );
258 struct initiator_cmd_t *hash_remove(hash_t * , uint32_t );
259 int             hash_destroy(hash_t * );
260 
261 /*
262  * Queuing
263  */
264 
265 typedef struct iscsi_queue_t {
266 	int             head;
267 	int             tail;
268 	int             count;
269 	void          **elem;
270 	int             depth;
271 	iscsi_spin_t    lock;
272 } iscsi_queue_t;
273 
274 int             iscsi_queue_init(iscsi_queue_t * , int );
275 void            iscsi_queue_destroy(iscsi_queue_t * );
276 int             iscsi_queue_insert(iscsi_queue_t * , void *);
277 void           *iscsi_queue_remove(iscsi_queue_t * );
278 int             iscsi_queue_depth(iscsi_queue_t * );
279 int             iscsi_queue_full(iscsi_queue_t * );
280 
281 /*
282  * Socket Abstraction
283  */
284 
285 /* Turning off Nagle's Algorithm doesn't always seem to work, */
286 /* so we combine two messages into one when the second's size */
287 /* is less than or equal to ISCSI_SOCK_HACK_CROSSOVER. */
288 
289 #define ISCSI_SOCK_HACK_CROSSOVER    1024
290 #define ISCSI_SOCK_CONNECT_NONBLOCK  0
291 #define ISCSI_SOCK_CONNECT_TIMEOUT   1
292 #define ISCSI_SOCK_MSG_BYTE_ALIGN    4
293 
294 int             iscsi_sock_create(int *);
295 int             iscsi_socks_establish(int *, int *, int *, char *, int);
296 int		iscsi_waitfor_connection(int *, int, const char *cf, int *);
297 const char	*iscsi_address_family(int);
298 int             iscsi_sock_setsockopt(int * , int , int , void *, unsigned);
299 int             iscsi_sock_getsockopt(int * , int , int , void *, unsigned *);
300 int             iscsi_sock_bind(int , int);
301 int             iscsi_sock_listen(int);
302 int             iscsi_sock_connect(int , char *, int);
303 int             iscsi_sock_accept(int , int *);
304 int             iscsi_sock_shutdown(int , int);
305 int             iscsi_sock_close(int);
306 int             iscsi_sock_msg(int , int , unsigned , void *, int);
307 int		iscsi_sock_send_header_and_data(int ,
308 				void *, unsigned ,
309 				const void *, unsigned , int);
310 int             iscsi_sock_getsockname(int , struct sockaddr * , unsigned *);
311 int             iscsi_sock_getpeername(int , struct sockaddr * , unsigned *);
312 int             modify_iov(struct iovec ** , int *, uint32_t , uint32_t);
313 
314 
315 /*
316  * Mutexes
317  */
318 
319 typedef pthread_mutex_t iscsi_mutex_t;
320 
321 int             iscsi_mutex_init(iscsi_mutex_t *);
322 int             iscsi_mutex_lock(iscsi_mutex_t *);
323 int             iscsi_mutex_unlock(iscsi_mutex_t *);
324 int             iscsi_mutex_destroy(iscsi_mutex_t *);
325 
326 #define ISCSI_LOCK(M, ELSE)	do {					\
327 	if (iscsi_mutex_lock(M) != 0) {					\
328 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_lock() failed\n");	\
329 		ELSE;							\
330 	}								\
331 } while (/* CONSTCOND */ 0)
332 
333 #define ISCSI_UNLOCK(M, ELSE)	do {					\
334 	if (iscsi_mutex_unlock(M) != 0) {				\
335 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_unlock() failed\n");	\
336 		ELSE;							\
337 	}								\
338 } while (/* CONSTCOND */ 0)
339 
340 #define ISCSI_MUTEX_INIT(M, ELSE) do {					\
341 	if (iscsi_mutex_init(M) != 0) {					\
342 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_init() failed\n");	\
343 		ELSE;							\
344 	}								\
345 } while (/* CONSTCOND */ 0)
346 
347 #define ISCSI_MUTEX_DESTROY(M, ELSE) do {				\
348 	if (iscsi_mutex_destroy(M) != 0) {				\
349 		iscsi_err(__FILE__, __LINE__, "iscsi_mutex_destroy() failed\n");	\
350 		ELSE;							\
351 	}								\
352 } while (/* CONSTCOND */ 0)
353 
354 /*
355  * Condition Variable
356  */
357 
358 typedef pthread_cond_t iscsi_cond_t;
359 
360 int             iscsi_cond_init(iscsi_cond_t *);
361 int             iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *);
362 int             iscsi_cond_signal(iscsi_cond_t *);
363 int             iscsi_cond_destroy(iscsi_cond_t *);
364 
365 #define ISCSI_COND_INIT(C, ELSE) do {					\
366 	if (iscsi_cond_init(C) != 0) {					\
367 		ELSE;							\
368 	}								\
369 } while (/* CONSTCOND */ 0)
370 
371 #define ISCSI_WAIT(C, M, ELSE)	do {					\
372 	if (iscsi_cond_wait(C, M) != 0) {				\
373 		ELSE;							\
374 	}								\
375 } while (/* CONSTCOND */ 0)
376 
377 #define ISCSI_SIGNAL(C, ELSE) 	do {					\
378 	if (iscsi_cond_signal(C) != 0) {				\
379 		ELSE;							\
380 	}								\
381 } while (/* CONSTCOND */ 0)
382 
383 #define ISCSI_COND_DESTROY(C, ELSE)	do {				\
384 	if (iscsi_cond_destroy(C) != 0) {				\
385 		ELSE;							\
386 	}								\
387 } while (/* CONSTCOND */ 0)
388 
389 /*
390  * Threading Routines
391  */
392 
393 typedef struct iscsi_thread_t {
394 	pthread_t       pthread;
395 } iscsi_thread_t;
396 
397 int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *);
398 
399 #define ISCSI_SET_THREAD(ME)	/* for user pthread id set by pthread_create
400 				 * in iscsi_thread_create */
401 #define ISCSI_THREAD_START(NAME)
402 
403 /*
404  * Worker Thread
405  */
406 
407 #define ISCSI_WORKER_STATE_STARTED   1
408 #define ISCSI_WORKER_STATE_ERROR     2
409 #define ISCSI_WORKER_STATE_EXITING   4
410 
411 typedef struct {
412 	iscsi_thread_t  thread;
413 	iscsi_mutex_t   work_mutex;
414 	iscsi_cond_t    work_cond;
415 	iscsi_mutex_t   exit_mutex;
416 	iscsi_cond_t    exit_cond;
417 	int             id;
418 	int             pid;
419 	volatile uint32_t state;
420 }               iscsi_worker_t;
421 
422 #define ISCSI_WORKER_EXIT(ME) do {					\
423 	iscsi_trace(TRACE_ISCSI_DEBUG, "%s:%d: %s", __FILE__, __LINE__, "exiting\n");\
424 	(ME)->state |= ISCSI_WORKER_STATE_EXITING;			\
425 	return 0;							\
426 	/* NOTREACHED */						\
427 } while (/* CONSTCOND */ 0)
428 
429 /*
430  * Spin Lock
431  */
432 #define ISCSI_SPIN
433 
434 /*
435  * Pre/Post condition checking
436  */
437 
438 #define NO_CLEANUP {}
439 
440 #if 0
441 #define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC)                       \
442 if ((V1)!=(V2)) {                                                    \
443   iscsi_err(__FILE__, __LINE__, "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2);    \
444   CU;                                                                \
445   return RC;                                                         \
446 }
447 #endif
448 
449 #if 0
450 #define ERROR_NOT_EQUAL(NAME, V1, V2, CU) 	do {			\
451 	if ((V1)!=(V2)) {						\
452 		iscsi_err(__FILE__, __LINE__,			\
453 			"Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
454 		CU;							\
455 	}								\
456 } while(/* CONSTCOND */0)
457 #endif
458 
459 /*
460  * Misc. Functions
461  */
462 
463 uint32_t iscsi_atoi(char *);
464 int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t);
465 int HexDataToText(uint8_t *, uint32_t , char *, uint32_t);
466 void GenRandomData(uint8_t *, uint32_t);
467 
468 /* this is the maximum number of iovecs which we can use in
469 * iscsi_sock_send_header_and_data */
470 #ifndef ISCSI_MAX_IOVECS
471 #define ISCSI_MAX_IOVECS        32
472 #endif
473 
474 enum {
475 	/* used in iscsi_sock_msg() */
476 	Receive = 0,
477 	Transmit = 1
478 };
479 
480 int		allow_netmask(const char *, const char *);
481 
482 #endif /* _ISCSIUTIL_H_ */
483