/* * 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 2007 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); /* * Misc functions */ int iscsitgt_svc_online(); #ifdef __cplusplus } #endif #endif /* _LIBISCSITGT_H */