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