From owner-svn-src-all@FreeBSD.ORG Thu Feb 19 14:52:04 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DDDBC42A; Thu, 19 Feb 2015 14:52:03 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C757FF56; Thu, 19 Feb 2015 14:52:03 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t1JEq3ef013975; Thu, 19 Feb 2015 14:52:03 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t1JEq1w7013965; Thu, 19 Feb 2015 14:52:01 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201502191452.t1JEq1w7013965@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Thu, 19 Feb 2015 14:52:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r279006 - stable/10/usr.sbin/ctld X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Feb 2015 14:52:04 -0000 Author: mav Date: Thu Feb 19 14:52:01 2015 New Revision: 279006 URL: https://svnweb.freebsd.org/changeset/base/279006 Log: 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. Modified: stable/10/usr.sbin/ctld/ctl.conf.5 stable/10/usr.sbin/ctld/ctld.c stable/10/usr.sbin/ctld/ctld.h stable/10/usr.sbin/ctld/discovery.c stable/10/usr.sbin/ctld/kernel.c stable/10/usr.sbin/ctld/login.c stable/10/usr.sbin/ctld/parse.y Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/ctld/ctl.conf.5 ============================================================================== --- stable/10/usr.sbin/ctld/ctl.conf.5 Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/ctl.conf.5 Thu Feb 19 14:52:01 2015 (r279006) @@ -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 Modified: stable/10/usr.sbin/ctld/ctld.c ============================================================================== --- stable/10/usr.sbin/ctld/ctld.c Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/ctld.c Thu Feb 19 14:52:01 2015 (r279006) @@ -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, cons 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 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 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 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 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 *ta 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 * 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 } /* - * 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); + TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) { + oldport = port_find(oldconf, newport->p_name); - if (oldtarg == NULL) - error = kernel_port_add(newtarg); - else { - target_set_ctl_port(newtarg, oldtarg->t_ctl_port); - error = kernel_port_update(newtarg); + 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. * Modified: stable/10/usr.sbin/ctld/ctld.h ============================================================================== --- stable/10/usr.sbin/ctld/ctld.h Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/ctld.h Thu Feb 19 14:52:01 2015 (r279006) @@ -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, 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 Modified: stable/10/usr.sbin/ctld/discovery.c ============================================================================== --- stable/10/usr.sbin/ctld/discovery.c Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/discovery.c Thu Feb 19 14:52:01 2015 (r279006) @@ -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 *respon 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 *respon 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 *respon 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); } } } Modified: stable/10/usr.sbin/ctld/kernel.c ============================================================================== --- stable/10/usr.sbin/ctld/kernel.c Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/kernel.c Thu Feb 19 14:52:01 2015 (r279006) @@ -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 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); Modified: stable/10/usr.sbin/ctld/login.c ============================================================================== --- stable/10/usr.sbin/ctld/login.c Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/login.c Thu Feb 19 14:52:01 2015 (r279006) @@ -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\"", Modified: stable/10/usr.sbin/ctld/parse.y ============================================================================== --- stable/10/usr.sbin/ctld/parse.y Thu Feb 19 14:40:50 2015 (r279005) +++ stable/10/usr.sbin/ctld/parse.y Thu Feb 19 14:52:01 2015 (r279006) @@ -652,21 +652,58 @@ target_initiator_portal: INITIATOR_PORTA } ; -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); } - target->t_portal_group = portal_group_find(conf, $2); - if (target->t_portal_group == NULL) { + 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); + } + 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); } ;