1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _LIBISCSITGT_H
#define _LIBISCSITGT_H
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Management API for the iSCSI Target.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* These includes resolve
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/iscsi_protocol.h>
#include <sys/scsi/generic/inquiry.h>
#define EUI64_SIZE 16
#define VID_SIZE 8
#define PID_SIZE 16
/*
* []------------------------------------------------------------------[]
* | Structures and enums returned by the list functions |
* []------------------------------------------------------------------[]
*/
typedef enum { LU_Offline, LU_Online } iscsit_status_t;
typedef enum { Target, Initiator, TPGT } iscsit_obj_type_t;
/*
* Logical Unit (LU) Structure.
* Each iSCSI Target has one or more Logical Units.
*/
typedef struct iscsit_lu {
/* This is the LU number for SCSI commands */
int l_num;
/* Globally unique identifier */
uint8_t l_guid[EUI64_SIZE];
/*
* VID/PID used in SCSI INQUIRY responses
*/
char l_vid[VID_SIZE],
l_pid[PID_SIZE];
/*
* Value will be one of DTYPE_DIRECT, DTYPE_SEQUENTIAL, etc ...
* Look at sys/scsi/generic/inquiry.h for full list
*/
uint8_t l_dtype;
/* Size of device in blocks */
diskaddr_t l_size;
iscsit_status_t l_status;
} iscsit_lu_t;
/*
* iSCSI Session information.
*/
typedef struct iscsit_conn {
char c_name[ISCSI_MAX_NAME_LEN],
*c_alias;
} iscsit_conn_t;
typedef struct iscsit_target {
/* This is the full IQN name of the target */
char t_name[ISCSI_MAX_NAME_LEN];
/*
* The Alias which is the same as "friendly name" used during the
* creation of the target.
*/
char *t_alias;
/*
* The number of Logical Units associated with this target.
* There will always be at least one LU with a value of 0.
* If there are more than LU the order is not guaranteed.
*/
int t_lu_count;
iscsit_lu_t **t_lu_list;
/*
* A list of initiator which may access this target. This list
* may be 0 in length.
*/
int t_acl_count;
char **t_acl_list;
/*
* Target Portal Group Tags. A value of zero for the count
* is valid.
*/
int t_tpgt_count;
char **t_tpgt_list;
/*
* The number of sessions that are currently attached to the
* target. Zero is valid.
*/
int t_conn_count;
iscsit_conn_t **t_conn_list;
} iscsit_target_t;
/*
* Information stored locally about initiators. Local initiator information
* is setup when administrators wish to control access to each target. The
* use of iSNS will be the prefered method once it's supported.
*/
typedef struct iscsit_initiator {
char i_name[ISCSI_MAX_NAME_LEN],
*i_chap_name;
/*
* While the target daemon has the CHAP secret available it's
* never returned. The CHAP name and secret can be changed at
* any time. This boolean will indicate if the CHAP secret is set
* and if so will cause the daemon to perform unidirectional
* authentication.
*/
boolean_t i_chap_secret_set;
} iscsit_initiator_t;
/*
* The list of IP addresses associated with a Target Portal Group Tag
*/
typedef struct iscsit_tpgt {
int t_ip_count;
struct sockaddr_storage **t_ip_list;
} iscsit_tpgt_t;
/*
* These are values which are used globally through the target daemon.
*/
typedef struct iscsit_admin {
/*
* This is the targets CHAP information. When an initiator needs
* to authenticate the target these values are used when creating
* the response.
*/
char *a_chap_name;
boolean_t a_chap_secret_set;
/*
* The location of the target configuration and default storage for LUs
*/
char *a_base_directory;
struct sockaddr_storage a_radius_server;
boolean_t a_radius_secret_set,
a_isns_discovery;
struct sockaddr_storage a_isns_ip;
boolean_t a_fast_write_ack;
} iscsit_admin_t;
typedef void *iscsit_handle_t;
/*
* []------------------------------------------------------------------[]
* | Funtion Prototypes |
* []------------------------------------------------------------------[]
*/
/*
* []------------------------------------------------------------------[]
* | Functions for ZFS |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_zfs_share -- advertise a ZFS volume through iSCSI
* iscsitgt_zfs_unshare -- unadvertise a ZFS volume through iSCSI
*
* dataset = this must be a valid ZFS dataset which has a "type" property
* of "volume".
*
* These functions will return 0 on success and -1 on failure setting errno
* thusly:
*
* ENODEV - dataset not found
* EINVAL - a share parameter has an invalid value
* ENOSYS - the option string cannot be understood for any other reason
*/
int iscsitgt_zfs_share(const char *dataset);
int iscsitgt_zfs_unshare(const char *dataset);
/*
* iscsitgt_zfs_is_shared -- returns 1 and 0 otherwise
*/
int iscsitgt_zfs_is_shared(const char *dataset);
/*
* []------------------------------------------------------------------[]
* | Functions to create handles which are used by methods defined below|
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_init -- Create a handle for each daemon
*
* A future release will enable this library to work to control multiple
* daemons on different hosts. For now, the argument 'host' should be
* set to NULL which will indicate the local host.
*/
iscsit_handle_t iscsitgt_init(char *host);
/*
* iscsitgt_fini -- free resources allocated by iscsitgt_init()
*/
void iscsitgt_fini(iscsit_handle_t h);
/*
* []------------------------------------------------------------------[]
* | Funtions for creating base objects |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_creat_target -- creates a new target/lu
*
* h = This is handle which indicates to which target the request is sent.
* If NULL, the target daemon on the current host is used.
* friendly_name = any ASCII string with the following restrictions.
* - it must be no more than 163 characters
* - it must only contain charcters from the set of 'a-z', 'A-Z', '0-9',
* ':', '.', or '-'
* The friendly_name will also be used as the iSCSI TargetAlias which
* is sent to the initiator as part of the log in parameters.
* lun = If the friendly_name has never been used before then lun must be 0.
* If friendly_name has already been created other luns will be created
* under that target. 0 <= lun <= 65535. NOTE: Using LUNs larger than
* 255 is not guaranteed to work for all initiators.
* size = The requested size for the device in blocks. There must be
* available space on the device for the create to succeed. size may
* be zero if, and only if, a 'backing' argument is given which exists.
* dtype = This indicates which type of emulation is performed by the
* daemon. Currently DTYPE_DIRECT, DTYPE_SEQUENTIAL, and DTYPE_UNKNOWN
* are supported. A dtype of DTYPE_UNKNOWN indicates to the daemon
* that a pass through mode should be used. For the pass through mode
* to work 'backing' must be a character device which supports the USCSI
* ioctl. For ZVOLs the dtype should be DTYPE_DIRECT.
* backing = optional location for the backing store. Normally the storage
* for the LU is created in the directory supplied to iscsit_mod_adm_store().
* If the 'backing' file name doesn't exist *and* a valid device 'size' is
* given then the backing store will be created in that location. When the
* target/lu is removed this backing store will also be removed.
*
* Return codes:
* EINVAL = one or more of the arguments are invalid
* ENOSPC = No space remains to create the backing store.
* EEXIST = A target with the same friendly_name already exists
*/
int iscsitgt_creat_target(iscsit_handle_t h, char *friendly_name,
int lun, diskaddr_t size, int dtype, char *backing);
/*
* iscsitgt_creat_initiator -- creates an initiator object
*
* Associates a fully compliant iSCSI name (IQN or EUI type) with
* a really human readable name.
*
* h = Handle used to communicate with remote target daemons. A NULL
* value may be used to indicate that the local host target daemon
* friendly_name = Any ASCII string.
* iqn_name = An initiator IQN or EUI string. There will be no validation
* of the name to determine if it complies with RFC3720. This way if
* an initiator has a poorly formed name we can still be configured to
* work with it.
*
* Return codes:
* 0 = success
* EEXIST = The friendly_name is already used.
*/
int iscsitgt_creat_initiator(iscsit_handle_t h, char *friendly_name,
char *iqn_name);
/*
* iscsitgt_creat_tpgt -- Create a Target Portal Group Tag
*
* Once a TPGT object has been created iscsitgt_add_tpgt_ip would be used
* to associate certain IP addresses with this TPGT. This is used to
* limit which NICs connections are accepted on for a given target.
* Once a TPGT is setup it can be added to a target using:
* iscsitgt_add_target_tpgt().
*
* h = See iscsitgt_creat_target
* tpgt_num = a value between 1 and 65535 inclusive
*
* Return codes:
* 0 = success
* EEXIST = A tpgt with that number already exists.
* EINVAL = TPGT must be a value between 1 and 65535 inclusive
*/
int iscsitgt_creat_tpgt(iscsit_handle_t h, int tpgt_num);
/*
* []------------------------------------------------------------------[]
* | Funtions for removing base objects |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_rem_target -- Removes a target/LU from the system
*
* Logical Unit Number 0 *must* be the last LUN removed from a target
* If not, an error will be returned. When LUN0 is removed all references
* to friendly_name are also removed from the system. e.g. Once the LU's
* are removed there's nothing else required to remove the target.
*
* h = See iscsitgt_creat_target()
* friendly_name = This is the same name used during the creation of
* the target.
* lun = Logical Unit Number
*
* Return codes:
* 0 = success
* ENOENT = either friendly_name wasn't found or lun not found
* EINVAL = attempt made to remove LUN0 while other LUs still exist.
*/
int iscsitgt_rem_target(iscsit_handle_t h, char *friendly_name,
int lun);
/*
* iscsitgt_rem_initiator -- Removes initiator object
*
* This method removes just the initiator object, but not any references
* to this object. For example let's say an initiator was called
* payroll_server and that this server was replaced with a new server
* that had the same function, but with a new IQN value and CHAP secret.
* The user of this library could then remove the initiator object
* and create a new one with the changes *without* needing to update all
* of the target objects that have a reference to 'payroll_server' in
* their ACLs. This is a security feature. If a target has a reference
* to an initiator object which doesn't exist, nobody will be able to
* log into the target. If the daemon we're to remove all references
* along with the object it would then be possible for an initiator to
* log into the target during the time the target didn't have a reference.
*
* h = See iscsitgt_creat_target()
* friendly_name = same value as that used during create.
*
* Return codes:
* 0 = success
* ENOENT = Can't find friendly_name
*/
int iscsitgt_rem_initiator(iscsit_handle_t h, char *friendly_name);
/*
* iscsitgt_rem_tpgt -- Removes a tpgt object
*
* Similar in function to iscsitgt_rem_initiator. This method only
* removes the TPGT object, but not any references to the object. This
* alows the administrator to remove an old TPGT and create a new one
* without needing to update each and every target first.
*
* h = See iscsitgt_creat_target
* tpgt_num = value used during create
*
* Return codes:
* 0 = success
* ENOENT = tpgt_num wasn't found
* EINVAL = a value outside of the accepted range for tpgt_num was used.
*/
int iscsitgt_rem_tpgt(iscsit_handle_t h, int tpgt_num);
/*
* []------------------------------------------------------------------[]
* | Funtions for adding attributes to base objects |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_add_target_initiator -- Adds an initiator object to ACL for target
*
* h = See iscsitgt_creat_target
* friendly_name = Existing target
* initiator = name of initiator object which doesn't need to exist before
* it's added.
*
* Return codes:
* 0 = success
* ENOENT = friendly_name doesn't exist.
*/
int iscsitgt_add_target_initiator(iscsit_handle_t h, char *friendly_name,
char *initiator);
/*
* iscsitgt_add_target_tpgt -- adds TPGT to the target
*
* h = See iscsitgt_creat_target()
* friendly_name = Must be a valid target object name
* tpgt_num = While the TPGT object doesn't need to exist, the value will
* be validated to see if it's within the valid range of 1 to 65535 inclusive
*
* Return codes:
* 0 = success
* ENOENT = friendly_name not found
* EINVAL = tpgt_num is not within the valid range.
*/
int iscsitgt_add_target_tpgt(iscsit_handle_t h, char *friendly_name,
int tpgt_num);
/*
* iscsitgt_add_tpgt_ip -- Adds IP address to TPGT object
*
* Return codes:
* 0 = success
* ENOENT = tpgt_num doesn't exist
* EINVAL = tpgt_num is not within the valid range
*/
int iscsitgt_add_tpgt_ip(iscsit_handle_t h, int tpgt_num,
struct sockaddr_storage *s);
/*
* []------------------------------------------------------------------[]
* | Funtions for deleting attributes from base objects |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_del_target_initiator -- Removes initiator from target ACL
*
* h = See iscsitgt_creat_target()
* friendly_name = target object
* initiator = initiator object to remove from ACL
*
* Return codes:
* 0 = success
* ENOENT = friendly_name or initiator don't exist
*/
int iscsitgt_del_target_initiator(iscsit_handle_t h, char *friendly_name,
char *initiator);
/*
* iscsitgt_del_target_tpgt -- Removes TPGT from specific target
*
* Return codes:
* 0 = success
* ENOENT = Either friendly_name or tpgt_num doesn't exist as a valid
* type
* EINVAL = tpgt_num is outside of the valid range (1 to 65535)
*/
int iscsitgt_del_target_tpgt(iscsit_handle_t h, char *friendly_name,
int tpgt_num);
/*
* iscsitgt_del_tpgt_ip -- Removes IP address from TPGT
*
* Return codes:
* 0 = success
* ENOENT = tpgt_num wasn't found or the IP address wasn't found within a valid
* tpgt
* EINVAL = tpgt_num is outside of the valid range (1 to 65535)
*/
int iscsitgt_del_tpgt_ip(iscsit_handle_t h, int tpgt_num,
struct sockaddr_storage *s);
/*
* []------------------------------------------------------------------[]
* | Funtions for modifying singular attributes for base objects |
* []------------------------------------------------------------------[]
*/
/*
* iscsitgt_mode_target_alias -- Modifies the TargetAlias associated with target
*
* By default the TargetAlias is the same as that given for the friendly_name.
* If another name is desired then it can be changed using this interface.
*
* h = See iscsitgt_creat_target()
* friendly_name = target object
*
* Return codes:
* 0 = success
* ENOENT = friendly_name doesn't exist
*/
int iscsitgt_mod_target_alias(iscsit_handle_t h, char *friendly_name,
char *alias);
int iscsitgt_mod_target_maxrec(iscsit_handle_t h, char *friendly_name,
size_t maxrecv);
int iscsitgt_mod_initiator_chap(iscsit_handle_t h,
char *friendly_name, char *chap_name, char *chap_secret);
int iscsitgt_mod_adm_store(iscsit_handle_t h, char *base);
int iscsitgt_mod_adm_chap(iscsit_handle_t h, char *chap_name,
char *chap_secret);
int iscsitgt_mod_adm_radius(iscsit_handle_t h, struct sockaddr_storage *s,
char *secret);
int iscsitgt_mod_adm_isns_discover(iscsit_handle_t h,
boolean_t find);
int iscsitgt_mod_adm_isns(iscsit_handle_t h,
struct sockaddr_storage *s);
int iscsitgt_mod_adm_fwa(iscsit_handle_t h, boolean_t enable);
/*
* []------------------------------------------------------------------[]
* | Funtions for listing objects |
* | |
* | NOTE: Each of the following function have a specific free routine |
* | which must be called to free the data. |
* []------------------------------------------------------------------[]
*/
/*
* iscsit_list_find -- returns list of specific object names.
*
* There are three types of objects which are manipulated by these
* interfaces (Target, Initiator, and TPGT). This function will return
* an array of character strings which represent all of the available
* objects of the specific type. These strings are the same ones that
* where used during the creation.
*
* NOTE: Since there's no locking a call to this this function may
* return a name which then doesn't exist when the user attempts to
* get the specific information on that object. This would be caused
* when another operator deletes an object between the first and second
* calls.
*/
char **iscsit_list_find(iscsit_handle_t h, iscsit_obj_type_t t);
void iscsit_list_free(char **list);
/*
* iscsit_list_target -- returns detailed information about a target
*/
iscsit_target_t *iscsit_list_target(iscsit_handle_t h, char *targ);
void iscsit_list_target_free(iscsit_target_t *t);
/*
* iscsit_list_initiator -- returns detailed information about an initiator
*/
iscsit_initiator_t *iscsit_list_initiator(iscsit_handle_t h, char *initiator);
void iscsit_list_initiator_free(iscsit_initiator_t *t);
/*
* iscsit_list_tpgt -- returns detailed information about a target port group
*/
iscsit_tpgt_t *iscsit_list_tpgt(iscsit_handle_t h, char *tpgt);
void iscsit_list_tpgt_free(iscsit_tpgt_t *t);
/*
* iscsit_list_adm -- returns information about the global variables used.
*/
iscsit_admin_t *iscsit_list_adm(iscsit_handle_t h);
void iscsit_list_adm_free(iscsit_admin_t *t);
#ifdef __cplusplus
}
#endif
#endif /* _LIBISCSITGT_H */
|