xref: /netbsd-src/external/bsd/iscsi/dist/include/iscsiutil.h (revision 1870a7f1300918057991dd71580343f7cfff1aa4)
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);
288 int		iscsi_sock_send_header_and_data(int ,
289 				void *, unsigned ,
290 				const void *, unsigned , int);
291 int             iscsi_sock_getsockname(int , struct sockaddr * , unsigned *);
292 int             iscsi_sock_getpeername(int , struct sockaddr * , unsigned *);
293 int             modify_iov(struct iovec ** , int *, uint32_t , uint32_t);
294 
295 
296 /*
297  * Mutexes
298  */
299 
300 typedef pthread_mutex_t iscsi_mutex_t;
301 
302 int             iscsi_mutex_init(iscsi_mutex_t *);
303 int             iscsi_mutex_lock(iscsi_mutex_t *);
304 int             iscsi_mutex_unlock(iscsi_mutex_t *);
305 int             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 
339 typedef pthread_cond_t iscsi_cond_t;
340 
341 int             iscsi_cond_init(iscsi_cond_t *);
342 int             iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *);
343 int             iscsi_cond_signal(iscsi_cond_t *);
344 int             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 
374 typedef struct iscsi_thread_t {
375 	pthread_t       pthread;
376 } iscsi_thread_t;
377 
378 int 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 
392 typedef 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)                       \
423 if ((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 
444 uint32_t iscsi_atoi(char *);
445 int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t);
446 int HexDataToText(uint8_t *, uint32_t , char *, uint32_t);
447 void 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 
455 enum {
456 	/* used in iscsi_sock_msg() */
457 	Receive = 0,
458 	Transmit = 1
459 };
460 
461 int		allow_netmask(const char *, const char *);
462 
463 #endif /* _ISCSIUTIL_H_ */
464