Partially merge of IET r307: allows to redirect initiators to another portals

+
Cleanups



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1735 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-06-03 19:17:52 +00:00
parent e2fef11118
commit ec3640be0b
11 changed files with 306 additions and 83 deletions
+11
View File
@@ -253,6 +253,15 @@ Each target subdirectory contains the following entries:
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
- redirect - allows to temporarily or permanently redirect login to the
target to another portal. Discovery sessions will not be impacted,
but normal sessions will be redirected before security negotiation.
The destination should be specified using format "<ip_addr>[:port] temp|perm".
IPv6 addresses need to be enclosed in [] brackets. To remove
redirection, provide an empty string. For example:
echo "10.170.77.2:32600 temp" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/redirect
will temporarily redirect login to portal 10.170.77.2 and port 32600.
- tid - TID of this target.
Subdirectory "sessions" contains one subdirectory for each connected
@@ -525,6 +534,7 @@ both iSCSI-SCST targets will look like:
| | | | `-- read_only
| | | `-- mgmt
| | |-- per_portal_acl
| | |-- redirect
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
@@ -586,6 +596,7 @@ both iSCSI-SCST targets will look like:
| | | | `-- read_only
| | | `-- mgmt
| | |-- per_portal_acl
| | |-- redirect
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
+11
View File
@@ -150,6 +150,15 @@ Each target subdirectory contains the following entries:
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
- redirect - allows to temporarily or permanently redirect login to the
target to another portal. Discovery sessions will not be impacted,
but normal sessions will be redirected before security negotiation.
The destination should be specified using format "<ip_addr>[:port] temp|perm".
IPv6 addresses need to be enclosed in [] brackets. To remove
redirection, provide an empty string. For example:
echo "10.170.77.2:32600 temp" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/redirect
will temporarily redirect login to portal 10.170.77.2 and port 32600.
- tid - TID of this target.
Subdirectory "sessions" contains one subdirectory for each connected
@@ -422,6 +431,7 @@ both iSCSI-SCST targets will look like:
| | | | `-- read_only
| | | `-- mgmt
| | |-- per_portal_acl
| | |-- redirect
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
@@ -483,6 +493,7 @@ both iSCSI-SCST targets will look like:
| | | | `-- read_only
| | | `-- mgmt
| | |-- per_portal_acl
| | |-- redirect
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
+9 -9
View File
@@ -996,8 +996,8 @@ int config_parse_main(const char *data, u32 cookie)
if (res < 0)
continue;
} else if (global_section &&
(!strcasecmp(p, ISCSI_ISNS_SERVER_PARAM_NAME) ||
!strcasecmp(p, ISCSI_ISNS_ACCESS_CONTROL_PARAM_NAME)))
(!strcasecmp(p, ISCSI_ISNS_SERVER_ATTR_NAME) ||
!strcasecmp(p, ISCSI_ISNS_ACCESS_CONTROL_ATTR_NAME)))
continue;
else {
log_error("Unknown or unexpected param: %s\n", p);
@@ -1041,9 +1041,9 @@ static int config_isns_load(const char *config)
p = config_sep_string(&q);
if ((*p == '\0') || (*p == '#'))
continue;
if (!strcasecmp(p, ISCSI_ISNS_SERVER_PARAM_NAME)) {
if (!strcasecmp(p, ISCSI_ISNS_SERVER_ATTR_NAME)) {
isns_server = strdup(config_sep_string(&q));
} else if (!strcasecmp(p, ISCSI_ISNS_ACCESS_CONTROL_PARAM_NAME)) {
} else if (!strcasecmp(p, ISCSI_ISNS_ACCESS_CONTROL_ATTR_NAME)) {
char *str = config_sep_string(&q);
if (!strcasecmp(str, "No"))
isns_access_control = 0;
@@ -1079,7 +1079,7 @@ int config_load(const char *config_name)
} else {
err = -errno;
log_error("Open config file %s failed: %s", cname,
strerror(err));
get_error_str(err));
goto out;
}
}
@@ -1087,21 +1087,21 @@ int config_load(const char *config_name)
size = lseek(config, 0, SEEK_END);
if (size < 0) {
err = -errno;
log_error("lseek() failed: %s", strerror(err));
log_error("lseek() failed: %s", get_error_str(err));
goto out_close;
}
buf = malloc(size+1);
if (buf == NULL) {
err = -ENOMEM;
log_error("malloc() failed: %s", strerror(err));
log_error("malloc() failed: %s", get_error_str(err));
goto out_close;
}
rc = lseek(config, 0, SEEK_SET);
if (rc < 0) {
err = -errno;
log_error("lseek() failed: %s", strerror(err));
log_error("lseek() failed: %s", get_error_str(err));
goto out_free;
}
@@ -1110,7 +1110,7 @@ int config_load(const char *config_name)
rc = read(config, &buf[i], size - i);
if (rc < 0) {
err = -errno;
log_error("read() failed: %s", strerror(err));
log_error("read() failed: %s", get_error_str(err));
goto out_free;
} else if (rc == 0)
break;
+15 -10
View File
@@ -88,7 +88,7 @@ int kernel_open(void)
if (err != 0) {
err = -errno;
log_error("Unable to register: %s. Incompatible version of the "
"kernel module?\n", strerror(errno));
"kernel module?\n", get_error_str(errno));
goto out_close;
} else {
log_debug(0, "max_data_seg_len %d, max_queued_cmds %d, ",
@@ -121,7 +121,7 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie)
info.tid = (tid != NULL) ? *tid : 0;
info.cookie = cookie;
info.attrs_num = 1;
info.attrs_num = 2;
for (j = 0; j < session_key_last; j++) {
if (session_keys[j].show_in_sysfs)
@@ -151,8 +151,13 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie)
i = 0;
kern_attrs[i].mode = 0644;
strlcpy(kern_attrs[i].name, ISCSI_PER_PORTAL_ACL,
sizeof(ISCSI_PER_PORTAL_ACL));
strlcpy(kern_attrs[i].name, ISCSI_PER_PORTAL_ACL_ATTR_NAME,
sizeof(ISCSI_PER_PORTAL_ACL_ATTR_NAME));
i++;
kern_attrs[i].mode = 0644;
strlcpy(kern_attrs[i].name, ISCSI_TARGET_REDIRECTION_ATTR_NAME,
sizeof(ISCSI_TARGET_REDIRECTION_ATTR_NAME));
i++;
for (j = 0; j < session_key_last; j++) {
@@ -196,7 +201,7 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie)
if ((err = ioctl(ctrl_fd, ADD_TARGET, &info)) < 0) {
err = -errno;
log_error("Can't create target %s: %s\n", target->name,
strerror(errno));
get_error_str(errno));
} else {
target->tid = err;
if (tid != NULL)
@@ -337,7 +342,7 @@ int kernel_params_get(u32 tid, u64 sid, int type, struct iscsi_param *params)
if ((err = ioctl(ctrl_fd, ISCSI_PARAM_GET, &info)) < 0) {
err = -errno;
log_debug(1, "Can't get session params for session 0x%" PRIx64
" (tid %u, err %d): %s\n", sid, tid, err, strerror(errno));
" (tid %u, err %d): %s\n", sid, tid, err, get_error_str(errno));
}
if (type == key_session)
@@ -380,7 +385,7 @@ int kernel_params_set(u32 tid, u64 sid, int type, u32 partial,
err = -errno;
log_error("Can't set session params for session 0x%" PRIx64
" (tid %u, type %d, partial %d, err %d): %s\n", sid,
tid, type, partial, err, strerror(errno));
tid, type, partial, err, get_error_str(errno));
}
out:
@@ -429,7 +434,7 @@ int kernel_session_create(struct connection *conn)
res = -errno;
log_error("Can't create sess 0x%" PRIx64 " (tid %d, "
"initiator %s): %s\n", conn->sess->sid.id64, conn->tid,
conn->sess->initiator, strerror(errno));
conn->sess->initiator, get_error_str(errno));
}
out:
@@ -450,7 +455,7 @@ int kernel_session_destroy(u32 tid, u64 sid)
if (res < 0) {
res = -errno;
log_debug(2, "Can't destroy sess 0x%" PRIx64 " (tid %d): %s\n",
sid, tid, strerror(errno));
sid, tid, get_error_str(errno));
}
return res;
@@ -475,7 +480,7 @@ int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
if (res < 0) {
res = -errno;
log_error("Can't create conn %x (sess 0x%" PRIx64 ", tid %d): %s\n",
cid, sid, tid, strerror(errno));
cid, sid, tid, get_error_str(errno));
}
return res;
+139 -18
View File
@@ -25,10 +25,10 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <arpa/inet.h>
#include <scst_const.h>
@@ -133,7 +133,7 @@ static int send_mgmt_cmd_res(u32 tid, u32 cookie, u32 req_cmd, int result,
if (res != 0) {
res = -errno;
log_error("Can't send mgmt reply (cookie %d, result %d, "
"res %d): %s\n", cookie, result, res, strerror(errno));
"res %d): %s\n", cookie, result, res, get_error_str(errno));
}
return res;
@@ -169,7 +169,7 @@ static int handle_e_add_target(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_ADD_TARGET, -errno, NULL);
exit(1);
}
@@ -185,7 +185,7 @@ static int handle_e_add_target(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_ADD_TARGET, -errno, NULL);
exit(1);
}
@@ -297,9 +297,9 @@ static int handle_add_attr(struct target *target, char *p, u32 cookie)
dir = params_index_by_name_numwild(pp, user_keys);
if (dir >= 0)
res = handle_add_user(target, dir, pp, p, cookie);
else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_NAME, pp) == 0)
else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_ATTR_NAME, pp) == 0)
res = __handle_add_attr(target, &target->allowed_portals,
ISCSI_ALLOWED_PORTAL_NAME, p, 1, cookie);
ISCSI_ALLOWED_PORTAL_ATTR_NAME, p, 1, cookie);
else {
log_error("Syntax error at %s", pp);
res = -EINVAL;
@@ -365,7 +365,7 @@ static int handle_del_attr(struct target *target, char *p, u32 cookie)
dir = params_index_by_name_numwild(pp, user_keys);
if (dir >= 0)
res = handle_del_user(target, dir, p, cookie);
else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_NAME, pp) == 0)
else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_ATTR_NAME, pp) == 0)
res = __handle_del_attr(target, &target->allowed_portals,
p, cookie);
else {
@@ -406,7 +406,7 @@ static int handle_e_mgmt_cmd(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_MGMT_CMD, -errno, NULL);
exit(1);
}
@@ -495,7 +495,7 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_GET_ATTR_VALUE, -errno, NULL);
exit(1);
}
@@ -547,7 +547,7 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
snprintf(res_str, sizeof(res_str), "%s %s\n", ISCSI_USER_NAME(user),
ISCSI_USER_PASS(user));
add_key_mark(res_str, sizeof(res_str), 0);
} else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_NAME, pp) == 0) {
} else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_ATTR_NAME, pp) == 0) {
struct iscsi_attr *portal;
if (target == NULL) {
@@ -573,7 +573,7 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
goto out_free;
}
snprintf(res_str, sizeof(res_str), "%d\n", iscsi_enabled);
} else if (strcasecmp(ISCSI_PER_PORTAL_ACL, pp) == 0) {
} else if (strcasecmp(ISCSI_PER_PORTAL_ACL_ATTR_NAME, pp) == 0) {
if (target == NULL) {
log_error("Target expected for attr %s", pp);
res = -EINVAL;
@@ -582,7 +582,26 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
snprintf(res_str, sizeof(res_str), "%d\n", target->per_portal_acl);
if (target->per_portal_acl)
add_key_mark(res_str, sizeof(res_str), 0);
}else if (strcasecmp(ISCSI_ISNS_SERVER_PARAM_NAME, pp) == 0) {
} else if (strcasecmp(ISCSI_TARGET_REDIRECTION_ATTR_NAME, pp) == 0) {
if (target == NULL) {
log_error("Target expected for attr %s", pp);
res = -EINVAL;
goto out_free;
}
if (strlen(target->redirect.addr) != 0) {
const char *type = (target->redirect.type == ISCSI_STATUS_TGT_MOVED_TEMP) ?
ISCSI_TARGET_REDIRECTION_VALUE_TEMP :
ISCSI_TARGET_REDIRECTION_VALUE_PERM;
if (target->redirect.port != ISCSI_LISTEN_PORT)
snprintf(res_str, sizeof(res_str), "%s:%d %s\n",
target->redirect.addr, target->redirect.port, type);
else
snprintf(res_str, sizeof(res_str), "%s %s\n",
target->redirect.addr, type);
add_key_mark(res_str, sizeof(res_str), 0);
} else
*res_str = '\0';
} else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) {
if (target != NULL) {
log_error("Not NULL target %s for global attribute %s",
target->name, pp);
@@ -611,6 +630,99 @@ out:
return res;
}
static int handle_target_redirect(struct target *target, char *p)
{
int res = 0;
char *addr, *type, *t, *port;
int port_num = ISCSI_LISTEN_PORT;
int type_num;
union {
struct in_addr ia4;
struct in6_addr ia6;
} ia;
addr = config_sep_string(&p);
if (*addr == '\0') {
log_info("Target redirection for %s cleared", target->name);
target->redirect.addr[0] = '\0';
goto out;
}
type = config_sep_string(&p);
if (*type == '\0') {
log_error("%s", "Redirection type required");
res = -EINVAL;
goto out;
}
t = config_sep_string(&p);
if (*t != '\0') {
log_error("%s", "Too many arguments for redirection");
res = -EINVAL;
goto out;
}
t = strrchr(addr, ']');
if (t != NULL)
port = strchr(t, ':');
else
port = strrchr(addr, ':');
if (port != NULL) {
*port = '\0';
port++;
port_num = strtol(port, (char **) NULL, 10);
if ((port_num <= 0) || (errno == EINVAL)) {
log_error("Invalid port %s", port);
res = -EINVAL;
goto out;
}
}
if (strlen(addr) >= sizeof(target->redirect.addr)) {
log_error("Too long addr %s, max allowed %d", addr,
sizeof(target->redirect.addr)-1);
res = -ERANGE;
goto out;
}
if (inet_pton(AF_INET, addr, &ia) != 1) {
char tmp[sizeof(target->redirect.addr)];
if (*addr == '[')
t = addr+1;
else
t = addr;
strlcpy(tmp, t, strchrnul(t, ']')-t+1);
if (inet_pton(AF_INET6, tmp, &ia) != 1) {
log_error("Invalid addr %s", addr);
res = -EINVAL;
goto out;
}
}
if (strcasecmp(type, ISCSI_TARGET_REDIRECTION_VALUE_TEMP) == 0) {
log_debug(1, "Temporary redirection");
type_num = ISCSI_STATUS_TGT_MOVED_TEMP;
} else if (strcasecmp(type, ISCSI_TARGET_REDIRECTION_VALUE_PERM) == 0) {
log_debug(1, "Permament redirection");
type_num = ISCSI_STATUS_TGT_MOVED_PERM;
} else {
log_error("Invalid redirection type %s", type);
res = -EINVAL;
goto out;
}
log_info("Target %s %s redirected to %s:%d", target->name,
(type_num == ISCSI_STATUS_TGT_MOVED_TEMP) ? "temporarily" : "permanently",
addr, port_num);
strcpy(target->redirect.addr, addr);
target->redirect.port = port_num;
target->redirect.type = type_num;
out:
return res;
}
static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
{
int res = 0, rc, idx;
@@ -646,7 +758,7 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_SET_ATTR_VALUE, -errno, NULL);
exit(1);
}
@@ -661,7 +773,7 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("read netlink fd (%d) failed: %s", fd,
strerror(errno));
get_error_str(errno));
send_mgmt_cmd_res(0, event->cookie, E_SET_ATTR_VALUE, -errno, NULL);
exit(1);
}
@@ -762,7 +874,7 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
res = account_replace(target, idx, pp, p);
if (res != 0)
goto out_free;
} else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_NAME, pp) == 0) {
} else if (strncasecmp_numwild(ISCSI_ALLOWED_PORTAL_ATTR_NAME, pp) == 0) {
struct iscsi_attr *portal;
if (target == NULL) {
@@ -798,7 +910,7 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
res = -EINVAL;
goto out_free;
}
} else if (strcasecmp(ISCSI_PER_PORTAL_ACL, pp) == 0) {
} else if (strcasecmp(ISCSI_PER_PORTAL_ACL_ATTR_NAME, pp) == 0) {
if (target == NULL) {
log_error("Target expected for attr %s", pp);
res = -EINVAL;
@@ -814,7 +926,16 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
res = -EINVAL;
goto out_free;
}
}else if (strcasecmp(ISCSI_ISNS_SERVER_PARAM_NAME, pp) == 0) {
} else if (strcasecmp(ISCSI_TARGET_REDIRECTION_ATTR_NAME, pp) == 0) {
if (target == NULL) {
log_error("Target expected for attr %s", pp);
res = -EINVAL;
goto out_free;
}
res = handle_target_redirect(target, p);
if (res != 0)
goto out_free;
} else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) {
if (target != NULL) {
log_error("Not NULL target %s for global attribute %s",
target->name, pp);
@@ -915,7 +1036,7 @@ retry:
return EAGAIN;
if (errno == EINTR)
goto retry;
log_error("read netlink fd (%d) failed: %s", fd, strerror(errno));
log_error("read netlink fd (%d) failed: %s", fd, get_error_str(errno));
exit(1);
}
+22 -21
View File
@@ -98,9 +98,9 @@ static void set_non_blocking(int fd)
if (res != -1) {
res = fcntl(fd, F_SETFL, res | O_NONBLOCK);
if (res)
log_warning("unable to set fd flags (%s)!", strerror(errno));
log_warning("unable to set fd flags (%s)!", get_error_str(errno));
} else
log_warning("unable to get fd flags (%s)!", strerror(errno));
log_warning("unable to get fd flags (%s)!", get_error_str(errno));
}
static void sock_set_keepalive(int sock, int timeout)
@@ -109,22 +109,22 @@ static void sock_set_keepalive(int sock, int timeout)
int opt = 2;
if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &opt, sizeof(opt)))
log_warning("unable to set TCP_KEEPCNT on server socket (%s)!", strerror(errno));
log_warning("unable to set TCP_KEEPCNT on server socket (%s)!", get_error_str(errno));
if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout)))
log_warning("unable to set TCP_KEEPIDLE on server socket (%s)!", strerror(errno));
log_warning("unable to set TCP_KEEPIDLE on server socket (%s)!", get_error_str(errno));
opt = 3;
if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &opt, sizeof(opt)))
log_warning("unable to set KEEPINTVL on server socket (%s)!", strerror(errno));
log_warning("unable to set KEEPINTVL on server socket (%s)!", get_error_str(errno));
opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)))
log_warning("unable to set SO_KEEPALIVE on server socket (%s)!", strerror(errno));
log_warning("unable to set SO_KEEPALIVE on server socket (%s)!", get_error_str(errno));
}
}
const char *get_EAI_error_str(int error)
const char *get_error_str(int error)
{
if (error == EAI_SYSTEM)
return strerror(errno);
@@ -148,7 +148,7 @@ static void create_listen_socket(struct pollfd *array)
rc = getaddrinfo(server_address, servname, &hints, &res0);
if (rc != 0) {
log_error("Unable to get address info (%s)!",
get_EAI_error_str(rc));
get_error_str(rc));
exit(1);
}
@@ -157,7 +157,7 @@ static void create_listen_socket(struct pollfd *array)
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock < 0) {
log_error("Unable to create server socket (%s) %d %d %d!",
strerror(errno), res->ai_family,
get_error_str(errno), res->ai_family,
res->ai_socktype, res->ai_protocol);
continue;
}
@@ -167,23 +167,23 @@ static void create_listen_socket(struct pollfd *array)
opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
log_warning("Unable to set SO_REUSEADDR on server socket (%s)!",
strerror(errno));
get_error_str(errno));
opt = 1;
if (res->ai_family == AF_INET6 &&
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))) {
log_error("Unable to restrict IPv6 socket (%s)", strerror(errno));
log_error("Unable to restrict IPv6 socket (%s)", get_error_str(errno));
close(sock);
continue;
}
if (bind(sock, res->ai_addr, res->ai_addrlen)) {
log_error("Unable to bind server socket (%s)!", strerror(errno));
log_error("Unable to bind server socket (%s)!", get_error_str(errno));
close(sock);
continue;
}
if (listen(sock, INCOMING_MAX)) {
log_error("Unable to listen to server socket (%s)!", strerror(errno));
log_error("Unable to listen to server socket (%s)!", get_error_str(errno));
close(sock);
continue;
}
@@ -231,7 +231,8 @@ static void accept_connection(int listen)
case ENETUNREACH:
break;
default:
perror("accept(incoming_socket) failed");
log_error("accept(incoming_socket) failed: %s",
get_error_str(errno));
exit(1);
}
goto out;
@@ -240,7 +241,7 @@ static void accept_connection(int listen)
namesize = sizeof(to);
rc = getsockname(fd, &to.sa, &namesize);
if (rc != 0) {
perror("getsockname() failed");
log_error("getsockname() failed: %s", get_error_str(errno));
goto out_close;
}
@@ -249,7 +250,7 @@ static void accept_connection(int listen)
NI_NUMERICHOST | NI_NUMERICSERV);
if (rc != 0) {
log_error("Target portal getnameinfo() failed: %s!",
get_EAI_error_str(rc));
get_error_str(rc));
goto out_close;
}
@@ -258,7 +259,7 @@ static void accept_connection(int listen)
sizeof(initiator_port), NI_NUMERICHOST | NI_NUMERICSERV);
if (rc != 0) {
log_error("Initiator getnameinfo() failed: %s!",
get_EAI_error_str(rc));
get_error_str(rc));
goto out_close;
}
@@ -526,7 +527,7 @@ static void event_loop(void)
"of iSCSI-SCST.", __FUNCTION__);
else
log_error("%s: poll() failed: %s", __FUNCTION__,
strerror(errno));
get_error_str(errno));
exit(1);
}
@@ -706,7 +707,7 @@ int main(int argc, char **argv)
init_max_params();
#ifndef CONFIG_SCST_PROC
err = kernel_attr_add(NULL, ISCSI_ISNS_SERVER_PARAM_NAME,
err = kernel_attr_add(NULL, ISCSI_ISNS_SERVER_ATTR_NAME,
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR, 0);
if (err != 0)
exit(err);
@@ -778,10 +779,10 @@ int main(int argc, char **argv)
exit(1);
if (gid && setgid(gid) < 0)
perror("setgid failed");
log_error("setgid failed: %s", get_error_str(errno));
if (uid && setuid(uid) < 0)
perror("setuid failed");
log_error("setuid failed: %s", get_error_str(errno));
event_loop();
+16 -2
View File
@@ -558,6 +558,20 @@ static void login_start(struct connection *conn)
return;
}
if (target_redirected(target, conn)) {
struct iscsi_login_rsp_hdr *rsp =
(struct iscsi_login_rsp_hdr *)&conn->rsp.bhs;
log_debug(1, "Redirecting target %s login to %s:%d",
target->name, target->redirect.addr,
target->redirect.port);
rsp->status_class = ISCSI_STATUS_REDIRECT;
rsp->status_detail = target->redirect.type;
conn->state = STATE_EXIT;
return;
}
conn->tid = target->tid;
if (!config_initiator_access_allowed(conn->tid, conn->fd) ||
@@ -574,7 +588,7 @@ static void login_start(struct connection *conn)
if (err != 0) {
log_error("Can't get session params for session 0x%" PRIx64
" (err %d): %s\n", conn->sid.id64, err,
strerror(-err));
get_error_str(-err));
login_rsp_tgt_err(conn, ISCSI_STATUS_TARGET_ERROR);
return;
}
@@ -991,7 +1005,7 @@ int cmnd_execute(struct connection *conn)
}
cmnd_exec_login(conn);
login_rsp = (struct iscsi_login_rsp_hdr *) &conn->rsp.bhs;
if (login_rsp->status_class)
if (login_rsp->status_class && login_rsp->status_class != ISCSI_STATUS_REDIRECT)
conn_free_rsp_buf_list(conn);
break;
case ISCSI_OP_TEXT_CMD:
+9 -1
View File
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/poll.h>
#include <assert.h>
#include <netdb.h>
#include "types.h"
#include "iscsi_hdr.h"
@@ -190,6 +191,12 @@ struct target {
char *alias;
unsigned int sessions_count;
struct redirect_addr {
char addr[NI_MAXHOST + 1];
int port;
u8 type; /* one of ISCSI_STATUS_TGT_MOVED_* constants */
} redirect;
struct __qelem target_in_accounts;
struct __qelem target_out_accounts;
@@ -235,7 +242,7 @@ extern void conn_free_rsp_buf_list(struct connection *conn);
extern uint16_t server_port;
extern struct iscsi_init_params iscsi_init_params;
extern void isns_set_fd(int isns, int scn_listen, int scn);
extern const char *get_EAI_error_str(int error);
extern const char *get_error_str(int error);
/* iscsid.c */
extern int iscsi_enabled;
@@ -288,6 +295,7 @@ extern int target_portal_allowed(struct target *target,
extern const char *iscsi_make_full_initiator_name(int per_portal_acl,
const char *initiator_name, const char *target_portal,
char *buf, int size);
extern bool target_redirected(struct target *target, struct connection *conn);
/* message.c */
extern int iscsi_adm_request_listen(void);
+18 -18
View File
@@ -100,14 +100,14 @@ static int isns_get_ip(int fd)
err = getsockname(fd, &lss.sa, &slen);
if (err) {
log_error("getsockname error: %s!", strerror(err));
log_error("getsockname error: %s!", get_error_str(err));
return err;
}
err = getnameinfo(&lss.sa, sizeof(lss),
eid, sizeof(eid), NULL, 0, 0);
if (err) {
log_error("getnameinfo error: %s!", get_EAI_error_str(err));
log_error("getnameinfo error: %s!", get_error_str(err));
return err;
}
@@ -138,7 +138,7 @@ static int isns_connect(void)
fd = socket(ss.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
log_error("unable to create (%s) %d!", strerror(errno),
log_error("unable to create (%s) %d!", get_error_str(errno),
ss.ss_family);
return -errno;
}
@@ -149,7 +149,7 @@ static int isns_connect(void)
*/
err = connect(fd, (struct sockaddr *) &ss, sizeof(ss));
if (err < 0) {
log_error("unable to connect (%s) %d!", strerror(errno),
log_error("unable to connect (%s) %d!", get_error_str(errno),
ss.ss_family);
close(fd);
return -errno;
@@ -226,7 +226,7 @@ static int isns_scn_deregister(char *name)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
return 0;
}
@@ -285,7 +285,7 @@ static int isns_scn_register(void)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
return 0;
}
@@ -340,7 +340,7 @@ static int isns_attr_query(char *name)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
return 0;
}
@@ -378,7 +378,7 @@ static int isns_deregister(void)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
return 0;
}
@@ -443,7 +443,7 @@ int isns_target_register(char *name)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
if (scn_listen_port)
isns_scn_register();
@@ -504,7 +504,7 @@ int isns_target_deregister(char *name)
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
return 0;
}
@@ -786,7 +786,7 @@ static int scn_accept_connection(void)
fd = accept(scn_listen_fd, &from.sa, &slen);
if (fd < 0) {
log_error("%s %d: accept error: %s", __func__, __LINE__,
strerror(errno));
get_error_str(errno));
return -errno;
}
log_error("Accept scn connection %d", fd);
@@ -794,7 +794,7 @@ static int scn_accept_connection(void)
err = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
if (err)
log_error("%s %d: %s\n", __func__, __LINE__,
strerror(errno));
get_error_str(errno));
/* not critical, so ignore. */
scn_fd = fd;
@@ -824,7 +824,7 @@ static void send_scn_rsp(char *name, uint16_t transaction)
err = write(scn_fd, buf, length + sizeof(struct isns_hdr));
if (err < 0)
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s", __func__, __LINE__, get_error_str(errno));
}
int isns_scn_handle(int is_accept)
@@ -882,7 +882,7 @@ static int scn_init(void)
fd = socket(ss.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
log_error("%s %d: %s\n", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s\n", __func__, __LINE__, get_error_str(errno));
err = -errno;
goto out;
}
@@ -892,21 +892,21 @@ static int scn_init(void)
err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
if (err) {
log_error("%s %d: %s\n", __func__, __LINE__,
strerror(errno));
get_error_str(errno));
goto out_close;
}
}
err = listen(fd, 5);
if (err) {
log_error("%s %d: %s\n", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s\n", __func__, __LINE__, get_error_str(errno));
goto out_close;
}
slen = sizeof(lss);
err = getsockname(fd, (struct sockaddr *) &lss, &slen);
if (err) {
log_error("%s %d: %s\n", __func__, __LINE__, strerror(errno));
log_error("%s %d: %s\n", __func__, __LINE__, get_error_str(errno));
goto out_close;
}
@@ -941,7 +941,7 @@ int isns_init(void)
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo(isns_server, (char *)&port, &hints, &res);
if (err) {
log_error("getaddrinfo error: %s, %s", get_EAI_error_str(err),
log_error("getaddrinfo error: %s, %s", get_error_str(err),
isns_server);
goto out;
}
+7 -4
View File
@@ -16,11 +16,14 @@
#ifndef PARAMS_H
#define PARAMS_H
#define ISCSI_ISNS_SERVER_PARAM_NAME "iSNSServer"
#define ISCSI_ISNS_ACCESS_CONTROL_PARAM_NAME "iSNSAccessControl"
#define ISCSI_ISNS_SERVER_ATTR_NAME "iSNSServer"
#define ISCSI_ISNS_ACCESS_CONTROL_ATTR_NAME "iSNSAccessControl"
#define ISCSI_ENABLED_ATTR_NAME "enabled"
#define ISCSI_ALLOWED_PORTAL_NAME "allowed_portal"
#define ISCSI_PER_PORTAL_ACL "per_portal_acl"
#define ISCSI_ALLOWED_PORTAL_ATTR_NAME "allowed_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"
#define ISCSI_TARGET_REDIRECTION_VALUE_PERM "perm"
struct iscsi_key;
+49
View File
@@ -425,3 +425,52 @@ int target_add(struct target *target, u32 *tid, u32 cookie)
out:
return err;
}
bool target_redirected(struct target *target, struct connection *conn)
{
bool res = false, rc;
union {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa;
socklen_t slen = sizeof(sa);
char tmp[NI_MAXHOST + 1];
char addr[NI_MAXHOST + 3];
char redirect[NI_MAXHOST + NI_MAXSERV + 4];
char *p;
if (strlen(target->redirect.addr) == 0)
goto out;
rc = getsockname(conn->fd, (struct sockaddr *)&sa.sa, &slen);
if (rc != 0) {
log_error("getsockname() failed: %s", get_error_str(errno));
goto out;
}
rc = getnameinfo(&sa.sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST);
if (rc != 0) {
log_error("getnameinfo() failed: %s", get_error_str(errno));
goto out;
}
if ((p = strrchr(tmp, '%')))
*p = '\0';
if (sa.sa.sa_family == AF_INET6)
snprintf(addr, sizeof(addr), "[%s]", tmp);
else
snprintf(addr, sizeof(addr), "%s", tmp);
snprintf(redirect, sizeof(redirect), "%s:%d", target->redirect.addr,
target->redirect.port);
if (strcmp(target->redirect.addr, addr)) {
text_key_add(conn, "TargetAddress", redirect);
res = true;
}
out:
return res;
}