diff --git a/iscsi-scst/README b/iscsi-scst/README index 4a275b195..91ad19109 100644 --- a/iscsi-scst/README +++ b/iscsi-scst/README @@ -200,6 +200,13 @@ is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries: iSCSI-SCST attributes before it starts accepting new connections. 0 by default. + - internal_portal - May designate one or more existing portals as being + internal. This will eliminate the need to supply a CHAP user/secret + during discovery or target login to any targets configured on those + portals. This is particularly useful for internal targets used as + part of ALUA configuration. Multiple addresses may be supplied, + separated by space characters. Empty by default. + - link_local - if set, makes the response to an IPv6 SendTargets include any link local addresses. Default is set. @@ -552,6 +559,7 @@ both iSCSI-SCST targets will look like: | |-- IncomingUser | |-- OutgoingUser | |-- enabled +| |-- internal_portal | |-- iSNSServer | |-- iqn.2006-10.net.vlnb:tgt | | |-- DataDigest diff --git a/iscsi-scst/usr/event.c b/iscsi-scst/usr/event.c index a65a1830f..67253b139 100644 --- a/iscsi-scst/usr/event.c +++ b/iscsi-scst/usr/event.c @@ -654,6 +654,18 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event) snprintf(res_str, sizeof(res_str), "%d\n", send_targets_link_local); if (send_targets_link_local != DEFAULT_SEND_TARGETS_LINK_LOCAL) add_key_mark(res_str, sizeof(res_str), 0); + } else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) { + if (target != NULL) { + log_error("Not NULL target %s for global attribute %s", + target->name, pp); + res = -EINVAL; + goto out_free; + } + if (internal_portal) { + snprintf(res_str, sizeof(res_str), "%s\n", internal_portal); + add_key_mark(res_str, sizeof(res_str), 0); + } else + snprintf(res_str, sizeof(res_str), "\n"); } else { log_error("Unknown attribute %s", pp); res = -EINVAL; @@ -669,6 +681,14 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event) return res; } +static bool is_addr(char *addr) +{ + struct in_addr ia; + struct in6_addr ia6; + + return (inet_pton(AF_INET, addr, &ia) == 1) || inet_pton(AF_INET6, addr, &ia6); +} + static int handle_target_redirect(struct target *target, char *p) { int res = 0; @@ -1094,6 +1114,53 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event) res = -EINVAL; goto out_free; } + } else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) { + if (target != NULL) { + log_error("Not NULL target %s for global attribute %s", + target->name, pp); + res = -EINVAL; + goto out_free; + } + p = config_strip_string(p); + if (!p || *p == '\0') { + if (internal_portal) + free(internal_portal); + internal_portal = NULL; + } else { + /* We have been provided with a string, check the contents. */ + if (strchr(p, ' ')) { + char *portals = strdup(p); + char *portal; + + if (!portals) { + log_error("Memory error (internal_portal)"); + res = -ENOMEM; + goto out_free; + } + + portal = strtok(portals, " "); + while(portal != NULL) { + if (!is_addr(portal)) { + free(portals); + log_error("Invalid address supplied %s", portal); + res = -EINVAL; + goto out_free; + } + portal = strtok(NULL, " "); + } + free(portals); + } else { + /* No spaces */ + if (!is_addr(p)) { + log_error("Invalid address supplied %s", p); + res = -EINVAL; + goto out_free; + } + } + if (internal_portal) + free(internal_portal); + internal_portal = strdup(p); + } } else { log_error("Unknown attribute %s", pp); res = -EINVAL; diff --git a/iscsi-scst/usr/iscsi_scstd.c b/iscsi-scst/usr/iscsi_scstd.c index 97b9143d2..60b83099f 100644 --- a/iscsi-scst/usr/iscsi_scstd.c +++ b/iscsi-scst/usr/iscsi_scstd.c @@ -962,6 +962,9 @@ int main(int argc, char **argv) if (err != 0) exit(err); err = kernel_attr_add(NULL, ISCSI_LINK_LOCAL_ATTR_NAME, 0644, 0); + if (err != 0) + exit(err); + err = kernel_attr_add(NULL, ISCSI_INTERNAL_PORTAL_ATTR_NAME, 0644, 0); if (err != 0) exit(err); diff --git a/iscsi-scst/usr/iscsid.c b/iscsi-scst/usr/iscsid.c index 1ef94ce3c..b7577910e 100644 --- a/iscsi-scst/usr/iscsid.c +++ b/iscsi-scst/usr/iscsid.c @@ -27,6 +27,7 @@ #include "iscsid.h" int iscsi_enabled; +char *internal_portal; static u32 ttt; @@ -1011,6 +1012,32 @@ static int cmnd_exec_auth(struct connection *conn) return res; } +static bool on_internal_portal(struct connection *conn) +{ + if (!internal_portal) + return false; + + if (strchr(internal_portal, ' ')) { + char *portals = strdup(internal_portal); + + if (portals) { + char *portal = strtok(portals, " "); + + while(portal != NULL) { + if (!strcmp(portal, conn->target_portal)) { + free(portals); + return true; + } + portal = strtok(NULL, " "); + } + free(portals); + } + return false; + } else { + return !strcmp(internal_portal, conn->target_portal); + } +} + static void cmnd_exec_login(struct connection *conn) { struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs; @@ -1084,7 +1111,8 @@ static void cmnd_exec_login(struct connection *conn) if (rsp->status_class) return; if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING)) - goto auth_err; + if (!on_internal_portal(conn)) + goto auth_err; if (rsp->status_class) return; text_scan_login(conn); diff --git a/iscsi-scst/usr/iscsid.h b/iscsi-scst/usr/iscsid.h index e68f67d7c..b3beb3a76 100644 --- a/iscsi-scst/usr/iscsid.h +++ b/iscsi-scst/usr/iscsid.h @@ -265,6 +265,7 @@ extern const char *get_error_str(int error); /* iscsid.c */ extern int iscsi_enabled; +extern char *internal_portal; extern int cmnd_execute(struct connection *conn); extern void cmnd_finish(struct connection *conn); diff --git a/iscsi-scst/usr/param.h b/iscsi-scst/usr/param.h index 9c9c62a47..e936c2593 100644 --- a/iscsi-scst/usr/param.h +++ b/iscsi-scst/usr/param.h @@ -21,6 +21,7 @@ #define ISCSI_ENABLED_ATTR_NAME "enabled" #define ISCSI_ISNS_ENTITY_ATTR_NAME "isns_entity_name" #define ISCSI_ALLOWED_PORTAL_ATTR_NAME "allowed_portal" +#define ISCSI_INTERNAL_PORTAL_ATTR_NAME "internal_portal" #define ISCSI_PER_PORTAL_ACL_ATTR_NAME "per_portal_acl" #define ISCSI_TARGET_REDIRECTION_ATTR_NAME "redirect" #define ISCSI_TARGET_REDIRECTION_VALUE_TEMP "temp"