mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 13:16:34 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user