summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ctld
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-02-19 14:52:01 +0000
committermav <mav@FreeBSD.org>2015-02-19 14:52:01 +0000
commitfa723dd3f0492dbf1b27c634d338c0d2aa30d671 (patch)
treebc4b50fd904a5f92845eb5f42541cf696256b86d /usr.sbin/ctld
parent8667ca9eb4f66121c921be56e31d2a67ab73513b (diff)
downloadFreeBSD-src-fa723dd3f0492dbf1b27c634d338c0d2aa30d671.zip
FreeBSD-src-fa723dd3f0492dbf1b27c634d338c0d2aa30d671.tar.gz
MFC r278322: Add support for multiple portal groups per target.
This change allows multiple "portal-group" options to be specified per target. Each of them may include new optional auth-group name parameter to override per-target auth parameters for specific portal group. Kernel side support was added earlier at r278161. Sponsored by: iXsystems, Inc.
Diffstat (limited to 'usr.sbin/ctld')
-rw-r--r--usr.sbin/ctld/ctl.conf.59
-rw-r--r--usr.sbin/ctld/ctld.c162
-rw-r--r--usr.sbin/ctld/ctld.h35
-rw-r--r--usr.sbin/ctld/discovery.c41
-rw-r--r--usr.sbin/ctld/kernel.c85
-rw-r--r--usr.sbin/ctld/login.c9
-rw-r--r--usr.sbin/ctld/parse.y49
7 files changed, 279 insertions, 111 deletions
diff --git a/usr.sbin/ctld/ctl.conf.5 b/usr.sbin/ctld/ctl.conf.5
index 29a0acb..6201788 100644
--- a/usr.sbin/ctld/ctl.conf.5
+++ b/usr.sbin/ctld/ctl.conf.5
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 1, 2015
+.Dd February 6, 2015
.Dt CTL.CONF 5
.Os
.Sh NAME
@@ -66,7 +66,7 @@ file is:
.No target Ar name {
.Dl auth-group Ar name
-.Dl portal-group Ar name
+.Dl portal-group Ar name Op Ar agname
.Dl lun Ar number Ar name
.Dl lun Ar number No {
.Dl path Ar path
@@ -310,12 +310,15 @@ This clause is mutually exclusive with
.Sy auth-group ;
one cannot use
both in a single target.
-.It Ic portal-group Ar name
+.It Ic portal-group Ar name Op Ar agname
Assign a previously defined portal group to the target.
The default portal group is
.Qq Ar default ,
which makes the target available
on TCP port 3260 on all configured IPv4 and IPv6 addresses.
+Optional second argument specifies auth group name for connections
+to this specific portal group.
+If second argument is not specified, target auth group is used.
.It Ic redirect Aq Ar address
IPv4 or IPv6 address to redirect initiators to.
When configured, all initiators attempting to connect to this target
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index c19b55a..513e073 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -91,6 +91,7 @@ conf_new(void)
TAILQ_INIT(&conf->conf_luns);
TAILQ_INIT(&conf->conf_targets);
TAILQ_INIT(&conf->conf_auth_groups);
+ TAILQ_INIT(&conf->conf_ports);
TAILQ_INIT(&conf->conf_portal_groups);
TAILQ_INIT(&conf->conf_isns);
@@ -124,6 +125,7 @@ conf_delete(struct conf *conf)
portal_group_delete(pg);
TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
isns_delete(is);
+ assert(TAILQ_EMPTY(&conf->conf_ports));
free(conf->conf_pidfile_path);
free(conf);
}
@@ -609,6 +611,7 @@ portal_group_new(struct conf *conf, const char *name)
log_err(1, "calloc");
pg->pg_name = checked_strdup(name);
TAILQ_INIT(&pg->pg_portals);
+ TAILQ_INIT(&pg->pg_ports);
pg->pg_conf = conf;
pg->pg_tag = 0; /* Assigned later in conf_apply(). */
TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
@@ -620,7 +623,10 @@ void
portal_group_delete(struct portal_group *pg)
{
struct portal *portal, *tmp;
+ struct port *port, *tport;
+ TAILQ_FOREACH_SAFE(port, &pg->pg_ports, p_pgs, tport)
+ port_delete(port);
TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next);
TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
@@ -784,6 +790,7 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
struct target *target;
struct portal *portal;
struct portal_group *pg;
+ struct port *port;
struct isns_req *req;
int res = 0;
uint32_t error;
@@ -807,11 +814,14 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
isns_req_add_32(req, 33, 1); /* 1 -- Target*/
if (target->t_alias != NULL)
isns_req_add_str(req, 34, target->t_alias);
- pg = target->t_portal_group;
- isns_req_add_32(req, 51, pg->pg_tag);
- TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
- isns_req_add_addr(req, 49, portal->p_ai);
- isns_req_add_port(req, 50, portal->p_ai);
+ TAILQ_FOREACH(port, &target->t_ports, p_ts) {
+ if ((pg = port->p_portal_group) == NULL)
+ continue;
+ isns_req_add_32(req, 51, pg->pg_tag);
+ TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
+ isns_req_add_addr(req, 49, portal->p_ai);
+ isns_req_add_port(req, 50, portal->p_ai);
+ }
}
}
res = isns_req_send(s, req);
@@ -1123,6 +1133,68 @@ valid_iscsi_name(const char *name)
return (true);
}
+struct port *
+port_new(struct conf *conf, struct target *target, struct portal_group *pg)
+{
+ struct port *port;
+
+ port = calloc(1, sizeof(*port));
+ if (port == NULL)
+ log_err(1, "calloc");
+ asprintf(&port->p_name, "%s-%s", pg->pg_name, target->t_name);
+ if (port_find(conf, port->p_name) != NULL) {
+ log_warnx("duplicate port \"%s\"", port->p_name);
+ free(port);
+ return (NULL);
+ }
+ port->p_conf = conf;
+ TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
+ TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts);
+ port->p_target = target;
+ TAILQ_INSERT_TAIL(&pg->pg_ports, port, p_pgs);
+ port->p_portal_group = pg;
+ return (port);
+}
+
+struct port *
+port_find(const struct conf *conf, const char *name)
+{
+ struct port *port;
+
+ TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
+ if (strcasecmp(port->p_name, name) == 0)
+ return (port);
+ }
+
+ return (NULL);
+}
+
+struct port *
+port_find_in_pg(const struct portal_group *pg, const char *target)
+{
+ struct port *port;
+
+ TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
+ if (strcasecmp(port->p_target->t_name, target) == 0)
+ return (port);
+ }
+
+ return (NULL);
+}
+
+void
+port_delete(struct port *port)
+{
+
+ if (port->p_portal_group)
+ TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs);
+ if (port->p_target)
+ TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts);
+ TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next);
+ free(port->p_name);
+ free(port);
+}
+
struct target *
target_new(struct conf *conf, const char *name)
{
@@ -1151,6 +1223,7 @@ target_new(struct conf *conf, const char *name)
targ->t_name[i] = tolower(targ->t_name[i]);
targ->t_conf = conf;
+ TAILQ_INIT(&targ->t_ports);
TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
return (targ);
@@ -1159,7 +1232,10 @@ target_new(struct conf *conf, const char *name)
void
target_delete(struct target *targ)
{
+ struct port *port, *tport;
+ TAILQ_FOREACH_SAFE(port, &targ->t_ports, p_ts, tport)
+ port_delete(port);
TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
free(targ->t_name);
@@ -1196,13 +1272,6 @@ target_set_redirection(struct target *target, const char *addr)
return (0);
}
-void
-target_set_ctl_port(struct target *target, uint32_t value)
-{
-
- target->t_ctl_port = value;
-}
-
struct lun *
lun_new(struct conf *conf, const char *name)
{
@@ -1508,6 +1577,7 @@ conf_verify(struct conf *conf)
{
struct auth_group *ag;
struct portal_group *pg;
+ struct port *port;
struct target *targ;
struct lun *lun;
bool found;
@@ -1527,10 +1597,10 @@ conf_verify(struct conf *conf)
"default");
assert(targ->t_auth_group != NULL);
}
- if (targ->t_portal_group == NULL) {
- targ->t_portal_group = portal_group_find(conf,
- "default");
- assert(targ->t_portal_group != NULL);
+ if (TAILQ_EMPTY(&targ->t_ports)) {
+ pg = portal_group_find(conf, "default");
+ assert(pg != NULL);
+ port_new(conf, targ, pg);
}
found = false;
for (i = 0; i < MAX_LUNS; i++) {
@@ -1558,20 +1628,14 @@ conf_verify(struct conf *conf)
if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN)
pg->pg_discovery_filter = PG_FILTER_NONE;
- TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
- if (targ->t_portal_group == pg)
- break;
- }
- if (pg->pg_redirection != NULL) {
- if (targ != NULL) {
+ if (!TAILQ_EMPTY(&pg->pg_ports)) {
+ if (pg->pg_redirection != NULL) {
log_debugx("portal-group \"%s\" assigned "
- "to target \"%s\", but configured "
+ "to target, but configured "
"for redirection",
- pg->pg_name, targ->t_name);
+ pg->pg_name);
}
pg->pg_unassigned = false;
- } else if (targ != NULL) {
- pg->pg_unassigned = false;
} else {
if (strcmp(pg->pg_name, "default") != 0)
log_warnx("portal-group \"%s\" not assigned "
@@ -1592,6 +1656,12 @@ conf_verify(struct conf *conf)
break;
}
}
+ TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
+ if (port->p_auth_group == ag) {
+ found = true;
+ break;
+ }
+ }
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
if (pg->pg_discovery_auth_group == ag) {
found = true;
@@ -1613,10 +1683,10 @@ conf_verify(struct conf *conf)
static int
conf_apply(struct conf *oldconf, struct conf *newconf)
{
- struct target *oldtarg, *newtarg, *tmptarg;
struct lun *oldlun, *newlun, *tmplun;
struct portal_group *oldpg, *newpg;
struct portal *oldp, *newp;
+ struct port *oldport, *newport, *tmpport;
struct isns *oldns, *newns;
pid_t otherpid;
int changed, cumulated_error = 0, error, sockbuf;
@@ -1684,17 +1754,17 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
* really happen, so leave it as it is for now.
*/
/*
- * First, remove any targets present in the old configuration
+ * First, remove any ports present in the old configuration
* and missing in the new one.
*/
- TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
- newtarg = target_find(newconf, oldtarg->t_name);
- if (newtarg != NULL)
+ TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) {
+ newport = port_find(newconf, oldport->p_name);
+ if (newport != NULL)
continue;
- error = kernel_port_remove(oldtarg);
+ error = kernel_port_remove(oldport);
if (error != 0) {
- log_warnx("failed to remove target %s",
- oldtarg->t_name);
+ log_warnx("failed to remove port %s",
+ oldport->p_name);
/*
* XXX: Uncomment after fixing the root cause.
*
@@ -1809,21 +1879,21 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
/*
- * Now add new targets or modify existing ones.
+ * Now add new ports or modify existing ones.
*/
- TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
- oldtarg = target_find(oldconf, newtarg->t_name);
-
- if (oldtarg == NULL)
- error = kernel_port_add(newtarg);
- else {
- target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
- error = kernel_port_update(newtarg);
+ TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) {
+ oldport = port_find(oldconf, newport->p_name);
+
+ if (oldport == NULL) {
+ error = kernel_port_add(newport);
+ } else {
+ newport->p_ctl_port = oldport->p_ctl_port;
+ error = kernel_port_update(newport);
}
if (error != 0) {
- log_warnx("failed to %s target %s",
- (oldtarg == NULL) ? "add" : "update",
- newtarg->t_name);
+ log_warnx("failed to %s port %s",
+ (oldport == NULL) ? "add" : "update",
+ newport->p_name);
/*
* XXX: Uncomment after fixing the root cause.
*
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
index 251351d..e213e0b 100644
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -119,11 +119,25 @@ struct portal_group {
int pg_discovery_filter;
bool pg_unassigned;
TAILQ_HEAD(, portal) pg_portals;
+ TAILQ_HEAD(, port) pg_ports;
char *pg_redirection;
uint16_t pg_tag;
};
+struct port {
+ TAILQ_ENTRY(port) p_next;
+ TAILQ_ENTRY(port) p_pgs;
+ TAILQ_ENTRY(port) p_ts;
+ struct conf *p_conf;
+ char *p_name;
+ struct auth_group *p_auth_group;
+ struct portal_group *p_portal_group;
+ struct target *p_target;
+
+ uint32_t p_ctl_port;
+};
+
struct lun_option {
TAILQ_ENTRY(lun_option) lo_next;
struct lun *lo_lun;
@@ -152,12 +166,10 @@ struct target {
struct conf *t_conf;
struct lun *t_luns[MAX_LUNS];
struct auth_group *t_auth_group;
- struct portal_group *t_portal_group;
+ TAILQ_HEAD(, port) t_ports;
char *t_name;
char *t_alias;
char *t_redirection;
-
- uint32_t t_ctl_port;
};
struct isns {
@@ -172,6 +184,7 @@ struct conf {
TAILQ_HEAD(, lun) conf_luns;
TAILQ_HEAD(, target) conf_targets;
TAILQ_HEAD(, auth_group) conf_auth_groups;
+ TAILQ_HEAD(, port) conf_ports;
TAILQ_HEAD(, portal_group) conf_portal_groups;
TAILQ_HEAD(, isns) conf_isns;
int conf_isns_period;
@@ -199,6 +212,7 @@ struct conf {
struct connection {
struct portal *conn_portal;
+ struct port *conn_port;
struct target *conn_target;
int conn_socket;
int conn_session_type;
@@ -317,14 +331,19 @@ void isns_register(struct isns *isns, struct isns *oldisns);
void isns_check(struct isns *isns);
void isns_deregister(struct isns *isns);
+struct port *port_new(struct conf *conf, struct target *target,
+ struct portal_group *pg);
+struct port *port_find(const struct conf *conf, const char *name);
+struct port *port_find_in_pg(const struct portal_group *pg,
+ const char *target);
+void port_delete(struct port *port);
+
struct target *target_new(struct conf *conf, const char *name);
void target_delete(struct target *target);
struct target *target_find(struct conf *conf,
const char *name);
int target_set_redirection(struct target *target,
const char *addr);
-void target_set_ctl_port(struct target *target,
- uint32_t value);
struct lun *lun_new(struct conf *conf, const char *name);
void lun_delete(struct lun *lun);
@@ -351,9 +370,9 @@ int kernel_lun_add(struct lun *lun);
int kernel_lun_resize(struct lun *lun);
int kernel_lun_remove(struct lun *lun);
void kernel_handoff(struct connection *conn);
-int kernel_port_add(struct target *targ);
-int kernel_port_update(struct target *targ);
-int kernel_port_remove(struct target *targ);
+int kernel_port_add(struct port *port);
+int kernel_port_update(struct port *port);
+int kernel_port_remove(struct port *port);
void kernel_capsicate(void);
#ifdef ICL_KERNEL_PROXY
diff --git a/usr.sbin/ctld/discovery.c b/usr.sbin/ctld/discovery.c
index b370e0b..88ca64c 100644
--- a/usr.sbin/ctld/discovery.c
+++ b/usr.sbin/ctld/discovery.c
@@ -162,6 +162,7 @@ logout_new_response(struct pdu *request)
static void
discovery_add_target(struct keys *response_keys, const struct target *targ)
{
+ struct port *port;
struct portal *portal;
char *buf;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
@@ -169,7 +170,10 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
int ret;
keys_add(response_keys, "TargetName", targ->t_name);
- TAILQ_FOREACH(portal, &targ->t_portal_group->pg_portals, p_next) {
+ TAILQ_FOREACH(port, &targ->t_ports, p_ts) {
+ if (port->p_portal_group == NULL)
+ continue;
+ TAILQ_FOREACH(portal, &port->p_portal_group->pg_portals, p_next) {
ai = portal->p_ai;
ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
@@ -183,13 +187,13 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
if (strcmp(hbuf, "0.0.0.0") == 0)
continue;
ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf,
- targ->t_portal_group->pg_tag);
+ port->p_portal_group->pg_tag);
break;
case AF_INET6:
if (strcmp(hbuf, "::") == 0)
continue;
ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf,
- targ->t_portal_group->pg_tag);
+ port->p_portal_group->pg_tag);
break;
default:
continue;
@@ -198,19 +202,24 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
log_err(1, "asprintf");
keys_add(response_keys, "TargetAddress", buf);
free(buf);
+ }
}
}
static bool
discovery_target_filtered_out(const struct connection *conn,
- const struct target *targ)
+ const struct port *port)
{
const struct auth_group *ag;
const struct portal_group *pg;
+ const struct target *targ;
const struct auth *auth;
int error;
- ag = targ->t_auth_group;
+ targ = port->p_target;
+ ag = port->p_auth_group;
+ if (ag == NULL)
+ ag = targ->t_auth_group;
pg = conn->conn_portal->p_portal_group;
assert(pg->pg_discovery_auth_group != PG_FILTER_UNKNOWN);
@@ -265,8 +274,8 @@ discovery(struct connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
+ const struct port *port;
const struct portal_group *pg;
- const struct target *targ;
const char *send_targets;
pg = conn->conn_portal->p_portal_group;
@@ -284,29 +293,23 @@ discovery(struct connection *conn)
response_keys = keys_new();
if (strcmp(send_targets, "All") == 0) {
- TAILQ_FOREACH(targ, &pg->pg_conf->conf_targets, t_next) {
- if (targ->t_portal_group != pg) {
- log_debugx("not returning target \"%s\"; "
- "belongs to a different portal group",
- targ->t_name);
- continue;
- }
- if (discovery_target_filtered_out(conn, targ)) {
+ TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
+ if (discovery_target_filtered_out(conn, port)) {
/* Ignore this target. */
continue;
}
- discovery_add_target(response_keys, targ);
+ discovery_add_target(response_keys, port->p_target);
}
} else {
- targ = target_find(pg->pg_conf, send_targets);
- if (targ == NULL) {
+ port = port_find_in_pg(pg, send_targets);
+ if (port == NULL) {
log_debugx("initiator requested information on unknown "
"target \"%s\"; returning nothing", send_targets);
} else {
- if (discovery_target_filtered_out(conn, targ)) {
+ if (discovery_target_filtered_out(conn, port)) {
/* Ignore this target. */
} else {
- discovery_add_target(response_keys, targ);
+ discovery_add_target(response_keys, port->p_target);
}
}
}
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index 02b616c..245134c 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -121,9 +121,10 @@ struct cctl_lun {
struct cctl_port {
uint32_t port_id;
- int cfiscsi_status;
+ int cfiscsi_state;
char *cfiscsi_target;
uint16_t cfiscsi_portal_group_tag;
+ char *ctld_portal_group_name;
STAILQ_HEAD(,cctl_lun_nv) attr_list;
STAILQ_ENTRY(cctl_port) links;
};
@@ -332,10 +333,13 @@ cctl_end_pelement(void *user_data, const char *name)
if (strcmp(name, "cfiscsi_target") == 0) {
cur_port->cfiscsi_target = str;
str = NULL;
- } else if (strcmp(name, "cfiscsi_status") == 0) {
- cur_port->cfiscsi_status = strtoul(str, NULL, 0);
+ } else if (strcmp(name, "cfiscsi_state") == 0) {
+ cur_port->cfiscsi_state = strtoul(str, NULL, 0);
} else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) {
cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0);
+ } else if (strcmp(name, "ctld_portal_group_name") == 0) {
+ cur_port->ctld_portal_group_name = str;
+ str = NULL;
} else if (strcmp(name, "targ_port") == 0) {
devlist->cur_port = NULL;
} else if (strcmp(name, "ctlportlist") == 0) {
@@ -373,6 +377,8 @@ conf_new_from_kernel(void)
{
struct conf *conf = NULL;
struct target *targ;
+ struct portal_group *pg;
+ struct port *cp;
struct lun *cl;
struct lun_option *lo;
struct ctl_lun_list list;
@@ -496,9 +502,9 @@ retry_port:
"ignoring", (uintmax_t)port->port_id);
continue;
}
- if (port->cfiscsi_status != 1) {
+ if (port->cfiscsi_state != 1) {
log_debugx("CTL port %ju is not active (%d); ignoring",
- (uintmax_t)port->port_id, port->cfiscsi_status);
+ (uintmax_t)port->port_id, port->cfiscsi_state);
continue;
}
@@ -514,6 +520,28 @@ retry_port:
continue;
}
}
+
+ if (port->ctld_portal_group_name == NULL)
+ continue;
+ pg = portal_group_find(conf, port->ctld_portal_group_name);
+ if (pg == NULL) {
+#if 0
+ log_debugx("found new kernel portal group %s for CTL port %ld",
+ port->ctld_portal_group_name, port->port_id);
+#endif
+ pg = portal_group_new(conf, port->ctld_portal_group_name);
+ if (pg == NULL) {
+ log_warnx("portal_group_new failed");
+ continue;
+ }
+ }
+ pg->pg_tag = port->cfiscsi_portal_group_tag;
+ cp = port_new(conf, targ, pg);
+ if (cp == NULL) {
+ log_warnx("port_new failed");
+ continue;
+ }
+ cp->p_ctl_port = port->port_id;
}
STAILQ_FOREACH(lun, &devlist.lun_list, links) {
@@ -804,32 +832,34 @@ kernel_handoff(struct connection *conn)
}
int
-kernel_port_add(struct target *targ)
+kernel_port_add(struct port *port)
{
struct ctl_port_entry entry;
struct ctl_req req;
struct ctl_lun_map lm;
+ struct target *targ = port->p_target;
+ struct portal_group *pg = port->p_portal_group;
char tagstr[16];
- int error, i;
+ int error, i, n;
/* Create iSCSI port. */
bzero(&req, sizeof(req));
strlcpy(req.driver, "iscsi", sizeof(req.driver));
req.reqtype = CTL_REQ_CREATE;
- req.num_args = 4;
req.args = malloc(req.num_args * sizeof(*req.args));
- req.args[0].namelen = sizeof("port_id");
- req.args[0].name = __DECONST(char *, "port_id");
- req.args[0].vallen = sizeof(targ->t_ctl_port);
- req.args[0].value = &targ->t_ctl_port;
- req.args[0].flags = CTL_BEARG_WR;
- str_arg(&req.args[1], "cfiscsi_target", targ->t_name);
- snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
- str_arg(&req.args[2], "cfiscsi_portal_group_tag", tagstr);
+ n = 0;
+ req.args[n].namelen = sizeof("port_id");
+ req.args[n].name = __DECONST(char *, "port_id");
+ req.args[n].vallen = sizeof(port->p_ctl_port);
+ req.args[n].value = &port->p_ctl_port;
+ req.args[n++].flags = CTL_BEARG_WR;
+ str_arg(&req.args[n++], "cfiscsi_target", targ->t_name);
+ snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
+ str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr);
if (targ->t_alias)
- str_arg(&req.args[3], "cfiscsi_target_alias", targ->t_alias);
- else
- req.num_args--;
+ str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias);
+ str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name);
+ req.num_args = n;
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
free(req.args);
if (error != 0) {
@@ -848,7 +878,7 @@ kernel_port_add(struct target *targ)
}
/* Explicitly enable mapping to block any access except allowed. */
- lm.port = targ->t_ctl_port;
+ lm.port = port->p_ctl_port;
lm.plun = UINT32_MAX;
lm.lun = 0;
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@@ -859,7 +889,7 @@ kernel_port_add(struct target *targ)
for (i = 0; i < MAX_LUNS; i++) {
if (targ->t_luns[i] == NULL)
continue;
- lm.port = targ->t_ctl_port;
+ lm.port = port->p_ctl_port;
lm.plun = i;
lm.lun = targ->t_luns[i]->l_ctl_lun;
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@@ -869,7 +899,7 @@ kernel_port_add(struct target *targ)
/* Enable port */
bzero(&entry, sizeof(entry));
- entry.targ_port = targ->t_ctl_port;
+ entry.targ_port = port->p_ctl_port;
error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry);
if (error != 0) {
log_warn("CTL_ENABLE_PORT ioctl failed");
@@ -880,14 +910,15 @@ kernel_port_add(struct target *targ)
}
int
-kernel_port_update(struct target *targ)
+kernel_port_update(struct port *port)
{
struct ctl_lun_map lm;
+ struct target *targ = port->p_target;
int error, i;
/* Map configured LUNs and unmap others */
for (i = 0; i < MAX_LUNS; i++) {
- lm.port = targ->t_ctl_port;
+ lm.port = port->p_ctl_port;
lm.plun = i;
if (targ->t_luns[i] == NULL)
lm.lun = UINT32_MAX;
@@ -901,10 +932,12 @@ kernel_port_update(struct target *targ)
}
int
-kernel_port_remove(struct target *targ)
+kernel_port_remove(struct port *port)
{
struct ctl_req req;
char tagstr[16];
+ struct target *targ = port->p_target;
+ struct portal_group *pg = port->p_portal_group;
int error;
bzero(&req, sizeof(req));
@@ -913,7 +946,7 @@ kernel_port_remove(struct target *targ)
req.num_args = 2;
req.args = malloc(req.num_args * sizeof(*req.args));
str_arg(&req.args[0], "cfiscsi_target", targ->t_name);
- snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
+ snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
index 5358e4b..865a19a 100644
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -827,19 +827,22 @@ login(struct connection *conn)
log_errx(1, "received Login PDU without TargetName");
}
- conn->conn_target = target_find(pg->pg_conf, target_name);
- if (conn->conn_target == NULL) {
+ conn->conn_port = port_find_in_pg(pg, target_name);
+ if (conn->conn_port == NULL) {
login_send_error(request, 0x02, 0x03);
log_errx(1, "requested target \"%s\" not found",
target_name);
}
+ conn->conn_target = conn->conn_port->p_target;
}
/*
* At this point we know what kind of authentication we need.
*/
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
- ag = conn->conn_target->t_auth_group;
+ ag = conn->conn_port->p_auth_group;
+ if (ag == NULL)
+ ag = conn->conn_target->t_auth_group;
if (ag->ag_name != NULL) {
log_debugx("initiator requests to connect "
"to target \"%s\"; auth-group \"%s\"",
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
index fead2ea..d0b2c51 100644
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -652,21 +652,58 @@ target_initiator_portal: INITIATOR_PORTAL STR
}
;
-target_portal_group: PORTAL_GROUP STR
+target_portal_group: PORTAL_GROUP STR STR
{
- if (target->t_portal_group != NULL) {
- log_warnx("portal-group for target \"%s\" "
- "specified more than once", target->t_name);
+ struct portal_group *tpg;
+ struct auth_group *tag;
+ struct port *tp;
+
+ tpg = portal_group_find(conf, $2);
+ if (tpg == NULL) {
+ log_warnx("unknown portal-group \"%s\" for target "
+ "\"%s\"", $2, target->t_name);
+ free($2);
+ free($3);
+ return (1);
+ }
+ tag = auth_group_find(conf, $3);
+ if (tag == NULL) {
+ log_warnx("unknown auth-group \"%s\" for target "
+ "\"%s\"", $3, target->t_name);
free($2);
+ free($3);
return (1);
}
- target->t_portal_group = portal_group_find(conf, $2);
- if (target->t_portal_group == NULL) {
+ tp = port_new(conf, target, tpg);
+ if (tp == NULL) {
+ log_warnx("can't link portal-group \"%s\" to target "
+ "\"%s\"", $2, target->t_name);
+ free($2);
+ return (1);
+ }
+ tp->p_auth_group = tag;
+ free($2);
+ free($3);
+ }
+ | PORTAL_GROUP STR
+ {
+ struct portal_group *tpg;
+ struct port *tp;
+
+ tpg = portal_group_find(conf, $2);
+ if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", $2, target->t_name);
free($2);
return (1);
}
+ tp = port_new(conf, target, tpg);
+ if (tp == NULL) {
+ log_warnx("can't link portal-group \"%s\" to target "
+ "\"%s\"", $2, target->t_name);
+ free($2);
+ return (1);
+ }
free($2);
}
;
OpenPOWER on IntegriCloud