Page MenuHomeFreeBSD

D48772.id150293.diff
No OneTemporary

D48772.id150293.diff

diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile
--- a/usr.sbin/ctld/Makefile
+++ b/usr.sbin/ctld/Makefile
@@ -5,8 +5,8 @@
PACKAGE= iscsi
PROG= ctld
-SRCS= ctld.c discovery.c isns.c kernel.c
-SRCS+= login.c parse.y token.l y.tab.h uclparse.c
+SRCS= ctld.c isns.c kernel.c
+SRCS+= parse.y token.l y.tab.h uclparse.c
CFLAGS+= -I${.CURDIR}
CFLAGS+= -I${SRCTOP}/sys
CFLAGS+= -I${SRCTOP}/sys/cam/ctl
@@ -25,6 +25,7 @@
.if ${MK_ISCSI} != "no"
CFLAGS+= -DWANT_ISCSI
+SRCS+= discovery.c iscsi.c login.c
.endif
.include <bsd.prog.mk>
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -47,8 +47,10 @@
#define DEFAULT_CD_BLOCKSIZE 2048
#define MAX_LUNS 1024
-#define MAX_DATA_SEGMENT_LENGTH (128 * 1024)
-#define SOCKBUF_SIZE 1048576
+
+struct ctl_req;
+struct port;
+struct target_protocol_ops;
struct auth {
TAILQ_ENTRY(auth) a_next;
@@ -62,16 +64,20 @@
struct auth_name {
TAILQ_ENTRY(auth_name) an_next;
struct auth_group *an_auth_group;
- char *an_initiator_name;
+ char *an_name;
+ int an_protocol;
};
+TAILQ_HEAD(auth_name_head, auth_name);
struct auth_portal {
TAILQ_ENTRY(auth_portal) ap_next;
struct auth_group *ap_auth_group;
- char *ap_initiator_portal;
+ char *ap_portal;
struct sockaddr_storage ap_sa;
int ap_mask;
+ int ap_protocol;
};
+TAILQ_HEAD(auth_portal_head, auth_portal);
#define AG_TYPE_UNKNOWN 0
#define AG_TYPE_DENY 1
@@ -86,16 +92,19 @@
struct target *ag_target;
int ag_type;
TAILQ_HEAD(, auth) ag_auths;
- TAILQ_HEAD(, auth_name) ag_names;
- TAILQ_HEAD(, auth_portal) ag_portals;
+ struct auth_name_head ag_initiator_names;
+ struct auth_portal_head ag_initiator_portals;
};
+#define PORTAL_PROTOCOL_ISCSI 0
+#define PORTAL_PROTOCOL_ISER 1
+
struct portal {
TAILQ_ENTRY(portal) p_next;
struct portal_group *p_portal_group;
- bool p_iser;
char *p_listen;
struct addrinfo *p_ai;
+ int p_protocol;
#ifdef ICL_KERNEL_PROXY
int p_id;
#endif
@@ -104,6 +113,35 @@
int p_socket;
};
+#define TARGET_PROTOCOL_ISCSI 0
+
+struct target_protocol_ops {
+ /* Initialize protocol-specific state for a new portal group. */
+ void (*portal_group_init)(struct portal_group *pg);
+
+ /* Copy protocol-specific state from oldpg to a new portal group. */
+ void (*portal_group_copy)(struct portal_group *oldpg,
+ struct portal_group *newpg);
+
+ /* Initialize protocol-specific state for a new portal. */
+ void (*portal_init)(struct portal *p);
+
+ /* Set protocol-specific socket options for a new socket. */
+ void (*portal_init_socket)(struct portal *p);
+
+ /* Initialize protocol-specific state for a new portal. */
+ void (*portal_delete)(struct portal *p);
+
+ /* Set req->driver and add fields to req->args_nvl. */
+ void (*kernel_port_add)(struct port *port, struct ctl_req *req);
+ void (*kernel_port_remove)(struct port *port, struct ctl_req *req);
+
+ char *(*validate_target_name)(const char *name);
+
+ void (*handle_connection)(struct portal *portal, int fd,
+ const char *host, const struct sockaddr *client_sa);
+};
+
#define PG_FILTER_UNKNOWN 0
#define PG_FILTER_NONE 1
#define PG_FILTER_PORTAL 2
@@ -118,6 +156,8 @@
struct auth_group *pg_discovery_auth_group;
int pg_discovery_filter;
int pg_foreign;
+ struct target_protocol_ops *pg_ops;
+ int pg_protocol;
bool pg_unassigned;
TAILQ_HEAD(, portal) pg_portals;
TAILQ_HEAD(, port) pg_ports;
@@ -185,6 +225,8 @@
char *t_redirection;
/* Name of this target's physical port, if any, i.e. "isp0" */
char *t_pport;
+ struct target_protocol_ops *t_ops;
+ int t_protocol;
};
struct isns {
@@ -246,6 +288,10 @@
struct chap *conn_chap;
};
+extern bool proxy_mode;
+extern int ctl_fd;
+extern struct target_protocol_ops target_iscsi;
+
int parse_conf(struct conf *newconf, const char *path);
int uclparse_conf(struct conf *conf, const char *path);
@@ -269,28 +315,33 @@
const struct auth *auth_find(const struct auth_group *ag,
const char *user);
-const struct auth_name *auth_name_new(struct auth_group *ag,
- const char *initiator_name);
-bool auth_name_defined(const struct auth_group *ag);
+const struct auth_name *auth_name_new(struct auth_group *ag, int protocol,
+ const char *name);
+bool auth_name_defined(const struct auth_group *ag,
+ int protocol);
const struct auth_name *auth_name_find(const struct auth_group *ag,
- const char *initiator_name);
+ int protocol, const char *name);
int auth_name_check(const struct auth_group *ag,
- const char *initiator_name);
+ int protocol, const char *name);
const struct auth_portal *auth_portal_new(struct auth_group *ag,
- const char *initiator_portal);
-bool auth_portal_defined(const struct auth_group *ag);
+ int protocol, const char *portal);
+bool auth_portal_defined(const struct auth_group *ag,
+ int protocol);
const struct auth_portal *auth_portal_find(const struct auth_group *ag,
+ int protocol,
const struct sockaddr_storage *sa);
int auth_portal_check(const struct auth_group *ag,
+ int protocol,
const struct sockaddr_storage *sa);
-struct portal_group *portal_group_new(struct conf *conf, const char *name);
+struct portal_group *portal_group_new(struct conf *conf, int protocol,
+ const char *name);
void portal_group_delete(struct portal_group *pg);
struct portal_group *portal_group_find(const struct conf *conf,
- const char *name);
+ int protocol, const char *name);
int portal_group_add_listen(struct portal_group *pg,
- const char *listen, bool iser);
+ const char *listen, int protocol);
int portal_group_set_filter(struct portal_group *pg,
const char *filter);
int portal_group_set_offload(struct portal_group *pg,
@@ -324,7 +375,8 @@
void port_delete(struct port *port);
int port_is_dummy(struct port *port);
-struct target *target_new(struct conf *conf, const char *name);
+struct target *target_new(struct conf *conf, const char *name,
+ int protocol);
void target_delete(struct target *target);
struct target *target_find(struct conf *conf,
const char *name);
@@ -351,7 +403,6 @@
int kernel_lun_add(struct lun *lun);
int kernel_lun_modify(struct lun *lun);
int kernel_lun_remove(struct lun *lun);
-void kernel_handoff(struct ctld_connection *conn);
int kernel_port_add(struct port *port);
int kernel_port_update(struct port *port, struct port *old);
int kernel_port_remove(struct port *port);
@@ -367,6 +418,8 @@
void kernel_receive(struct pdu *pdu);
#endif
+bool timed_out(void);
+
void login(struct ctld_connection *conn);
void discovery(struct ctld_connection *conn);
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -53,13 +53,6 @@
#include "ctld.h"
#include "isns.h"
-static bool timed_out(void);
-#ifdef ICL_KERNEL_PROXY
-static void pdu_receive_proxy(struct pdu *pdu);
-static void pdu_send_proxy(struct pdu *pdu);
-#endif /* ICL_KERNEL_PROXY */
-static void pdu_fail(const struct connection *conn, const char *reason);
-
bool proxy_mode = false;
static volatile bool sighup_received = false;
@@ -68,16 +61,6 @@
static int kqfd;
static int nchildren = 0;
-static uint16_t last_portal_group_tag = 0xff;
-
-static struct connection_ops conn_ops = {
- .timed_out = timed_out,
-#ifdef ICL_KERNEL_PROXY
- .pdu_receive_proxy = pdu_receive_proxy,
- .pdu_send_proxy = pdu_send_proxy,
-#endif
- .fail = pdu_fail,
-};
static void
usage(void)
@@ -296,44 +279,74 @@
return (auth);
}
+static struct auth_name_head *
+auth_name_head(struct auth_group *ag, int protocol)
+{
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ return (&ag->ag_initiator_names);
+ default:
+ __assert_unreachable();
+ }
+}
+
+static const struct auth_name_head *
+auth_name_const_head(const struct auth_group *ag, int protocol)
+{
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ return (&ag->ag_initiator_names);
+ default:
+ __assert_unreachable();
+ }
+}
+
const struct auth_name *
-auth_name_new(struct auth_group *ag, const char *name)
+auth_name_new(struct auth_group *ag, int protocol, const char *name)
{
+ struct auth_name_head *head = auth_name_head(ag, protocol);
struct auth_name *an;
an = calloc(1, sizeof(*an));
if (an == NULL)
log_err(1, "calloc");
an->an_auth_group = ag;
- an->an_initiator_name = checked_strdup(name);
- TAILQ_INSERT_TAIL(&ag->ag_names, an, an_next);
+ an->an_name = checked_strdup(name);
+ an->an_protocol = protocol;
+ TAILQ_INSERT_TAIL(head, an, an_next);
return (an);
}
static void
auth_name_delete(struct auth_name *an)
{
- TAILQ_REMOVE(&an->an_auth_group->ag_names, an, an_next);
+ struct auth_name_head *head;
- free(an->an_initiator_name);
+ head = auth_name_head(an->an_auth_group, an->an_protocol);
+ TAILQ_REMOVE(head, an, an_next);
+
+ free(an->an_name);
free(an);
}
bool
-auth_name_defined(const struct auth_group *ag)
+auth_name_defined(const struct auth_group *ag, int protocol)
{
- if (TAILQ_EMPTY(&ag->ag_names))
+ const struct auth_name_head *head = auth_name_const_head(ag, protocol);
+
+ if (TAILQ_EMPTY(head))
return (false);
return (true);
}
const struct auth_name *
-auth_name_find(const struct auth_group *ag, const char *name)
+auth_name_find(const struct auth_group *ag, int protocol, const char *name)
{
+ const struct auth_name_head *head = auth_name_const_head(ag, protocol);
const struct auth_name *auth_name;
- TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) {
- if (strcmp(auth_name->an_initiator_name, name) == 0)
+ TAILQ_FOREACH(auth_name, head, an_next) {
+ if (strcmp(auth_name->an_name, name) == 0)
return (auth_name);
}
@@ -341,20 +354,43 @@
}
int
-auth_name_check(const struct auth_group *ag, const char *initiator_name)
+auth_name_check(const struct auth_group *ag, int protocol, const char *name)
{
- if (!auth_name_defined(ag))
+ if (!auth_name_defined(ag, protocol))
return (0);
- if (auth_name_find(ag, initiator_name) == NULL)
+ if (auth_name_find(ag, protocol, name) == NULL)
return (1);
return (0);
}
+static struct auth_portal_head *
+auth_portal_head(struct auth_group *ag, int protocol)
+{
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ return (&ag->ag_initiator_portals);
+ default:
+ __assert_unreachable();
+ }
+}
+
+static const struct auth_portal_head *
+auth_portal_const_head(const struct auth_group *ag, int protocol)
+{
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ return (&ag->ag_initiator_portals);
+ default:
+ __assert_unreachable();
+ }
+}
+
const struct auth_portal *
-auth_portal_new(struct auth_group *ag, const char *portal)
+auth_portal_new(struct auth_group *ag, int protocol, const char *portal)
{
+ struct auth_portal_head *head = auth_portal_head(ag, protocol);
struct auth_portal *ap;
char *net, *mask, *str, *tmp;
int len, dm, m;
@@ -363,7 +399,7 @@
if (ap == NULL)
log_err(1, "calloc");
ap->ap_auth_group = ag;
- ap->ap_initiator_portal = checked_strdup(portal);
+ ap->ap_portal = checked_strdup(portal);
mask = str = checked_strdup(portal);
net = strsep(&mask, "/");
if (net[0] == '[')
@@ -399,8 +435,9 @@
} else
m = dm;
ap->ap_mask = m;
+ ap->ap_protocol = protocol;
free(str);
- TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
+ TAILQ_INSERT_TAIL(head, ap, ap_next);
return (ap);
error:
@@ -413,29 +450,38 @@
static void
auth_portal_delete(struct auth_portal *ap)
{
- TAILQ_REMOVE(&ap->ap_auth_group->ag_portals, ap, ap_next);
+ struct auth_portal_head *head;
- free(ap->ap_initiator_portal);
+ head = auth_portal_head(ap->ap_auth_group, ap->ap_protocol);
+ TAILQ_REMOVE(head, ap, ap_next);
+
+ free(ap->ap_portal);
free(ap);
}
bool
-auth_portal_defined(const struct auth_group *ag)
+auth_portal_defined(const struct auth_group *ag, int protocol)
{
- if (TAILQ_EMPTY(&ag->ag_portals))
+ const struct auth_portal_head *head;
+
+ head = auth_portal_const_head(ag, protocol);
+ if (TAILQ_EMPTY(head))
return (false);
return (true);
}
const struct auth_portal *
-auth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss)
+auth_portal_find(const struct auth_group *ag, int protocol,
+ const struct sockaddr_storage *ss)
{
+ const struct auth_portal_head *head;
const struct auth_portal *ap;
const uint8_t *a, *b;
int i;
uint8_t bmask;
- TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) {
+ head = auth_portal_const_head(ag, protocol);
+ TAILQ_FOREACH(ap, head, ap_next) {
if (ap->ap_sa.ss_family != ss->ss_family)
continue;
if (ss->ss_family == AF_INET) {
@@ -467,13 +513,14 @@
}
int
-auth_portal_check(const struct auth_group *ag, const struct sockaddr_storage *sa)
+auth_portal_check(const struct auth_group *ag, int protocol,
+ const struct sockaddr_storage *sa)
{
- if (!auth_portal_defined(ag))
+ if (!auth_portal_defined(ag, protocol))
return (0);
- if (auth_portal_find(ag, sa) == NULL)
+ if (auth_portal_find(ag, protocol, sa) == NULL)
return (1);
return (0);
@@ -498,8 +545,8 @@
if (name != NULL)
ag->ag_name = checked_strdup(name);
TAILQ_INIT(&ag->ag_auths);
- TAILQ_INIT(&ag->ag_names);
- TAILQ_INIT(&ag->ag_portals);
+ TAILQ_INIT(&ag->ag_initiator_names);
+ TAILQ_INIT(&ag->ag_initiator_portals);
ag->ag_conf = conf;
TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
@@ -517,9 +564,10 @@
TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, auth_tmp)
auth_delete(auth);
- TAILQ_FOREACH_SAFE(auth_name, &ag->ag_names, an_next, auth_name_tmp)
+ TAILQ_FOREACH_SAFE(auth_name, &ag->ag_initiator_names, an_next,
+ auth_name_tmp)
auth_name_delete(auth_name);
- TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_portals, ap_next,
+ TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_initiator_portals, ap_next,
auth_portal_tmp)
auth_portal_delete(auth_portal);
free(ag->ag_name);
@@ -598,7 +646,7 @@
static void
portal_delete(struct portal *portal)
{
-
+ portal->p_portal_group->pg_ops->portal_delete(portal);
TAILQ_REMOVE(&portal->p_portal_group->pg_portals, portal, p_next);
if (portal->p_ai != NULL)
freeaddrinfo(portal->p_ai);
@@ -606,14 +654,39 @@
free(portal);
}
+static struct target_protocol_ops *
+target_ops(int protocol)
+{
+ switch (protocol) {
+#ifdef WANT_ISCSI
+ case TARGET_PROTOCOL_ISCSI:
+ return (&target_iscsi);
+#endif
+ default:
+ return (NULL);
+ }
+}
+
+static const char *
+portal_group_keyword(int protocol)
+{
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ return "portal-group";
+ default:
+ __assert_unreachable();
+ }
+}
+
struct portal_group *
-portal_group_new(struct conf *conf, const char *name)
+portal_group_new(struct conf *conf, int protocol, const char *name)
{
struct portal_group *pg;
- pg = portal_group_find(conf, name);
+ pg = portal_group_find(conf, protocol, name);
if (pg != NULL) {
- log_warnx("duplicated portal-group \"%s\"", name);
+ log_warnx("duplicated %s \"%s\"",
+ portal_group_keyword(protocol), name);
return (NULL);
}
@@ -624,6 +697,8 @@
pg->pg_options = nvlist_create(0);
TAILQ_INIT(&pg->pg_portals);
TAILQ_INIT(&pg->pg_ports);
+ pg->pg_protocol = protocol;
+ pg->pg_ops = target_ops(protocol);
pg->pg_conf = conf;
pg->pg_tag = 0; /* Assigned later in conf_apply(). */
pg->pg_dscp = -1;
@@ -653,12 +728,13 @@
}
struct portal_group *
-portal_group_find(const struct conf *conf, const char *name)
+portal_group_find(const struct conf *conf, int protocol, const char *name)
{
struct portal_group *pg;
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- if (strcmp(pg->pg_name, name) == 0)
+ if (pg->pg_protocol == protocol &&
+ strcmp(pg->pg_name, name) == 0)
return (pg);
}
@@ -723,15 +799,26 @@
}
int
-portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
+portal_group_add_listen(struct portal_group *pg, const char *value,
+ int protocol)
{
struct portal *portal;
+ const char *def_port;
portal = portal_new(pg);
portal->p_listen = checked_strdup(value);
- portal->p_iser = iser;
+ portal->p_protocol = protocol;
- if (parse_addr_port(portal->p_listen, "3260", &portal->p_ai)) {
+ switch (protocol) {
+ case PORTAL_PROTOCOL_ISER:
+ case PORTAL_PROTOCOL_ISCSI:
+ def_port = "3260";
+ break;
+ default:
+ __builtin_unreachable();
+ }
+
+ if (parse_addr_port(portal->p_listen, def_port, &portal->p_ai)) {
log_warnx("invalid listen address %s", portal->p_listen);
portal_delete(portal);
return (1);
@@ -742,6 +829,7 @@
* those into multiple portals.
*/
+ pg->pg_ops->portal_init(portal);
return (0);
}
@@ -828,6 +916,8 @@
}
}
TAILQ_FOREACH(target, &conf->conf_targets, t_next) {
+ if (target->t_protocol != TARGET_PROTOCOL_ISCSI)
+ continue;
isns_req_add_str(req, 32, target->t_name);
isns_req_add_32(req, 33, 1); /* 1 -- Target*/
if (target->t_alias != NULL)
@@ -1280,31 +1370,31 @@
}
struct target *
-target_new(struct conf *conf, const char *name)
+target_new(struct conf *conf, const char *name, int protocol)
{
+ struct target_protocol_ops *ops;
struct target *targ;
- int i, len;
+ char *t_name;
targ = target_find(conf, name);
if (targ != NULL) {
log_warnx("duplicated target \"%s\"", name);
return (NULL);
}
- if (valid_iscsi_name(name, log_warnx) == false) {
+ ops = target_ops(protocol);
+ if (ops == NULL) {
+ log_warnx("unsupported protocol for target \"%s\"", name);
return (NULL);
}
+ t_name = ops->validate_target_name(name);
+ if (t_name == NULL)
+ return (NULL);
targ = calloc(1, sizeof(*targ));
if (targ == NULL)
log_err(1, "calloc");
- targ->t_name = checked_strdup(name);
-
- /*
- * RFC 3722 requires us to normalize the name to lowercase.
- */
- len = strlen(name);
- for (i = 0; i < len; i++)
- targ->t_name[i] = tolower(targ->t_name[i]);
-
+ targ->t_name = t_name;
+ targ->t_ops = ops;
+ targ->t_protocol = protocol;
targ->t_conf = conf;
TAILQ_INIT(&targ->t_ports);
TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
@@ -1498,63 +1588,6 @@
return (true);
}
-#ifdef ICL_KERNEL_PROXY
-
-static void
-pdu_receive_proxy(struct pdu *pdu)
-{
- struct connection *conn;
- size_t len;
-
- assert(proxy_mode);
- conn = pdu->pdu_connection;
-
- kernel_receive(pdu);
-
- len = pdu_ahs_length(pdu);
- if (len > 0)
- log_errx(1, "protocol error: non-empty AHS");
-
- len = pdu_data_segment_length(pdu);
- assert(len <= (size_t)conn->conn_max_recv_data_segment_length);
- pdu->pdu_data_len = len;
-}
-
-static void
-pdu_send_proxy(struct pdu *pdu)
-{
-
- assert(proxy_mode);
-
- pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
- kernel_send(pdu);
-}
-
-#endif /* ICL_KERNEL_PROXY */
-
-static void
-pdu_fail(const struct connection *conn __unused, const char *reason __unused)
-{
-}
-
-static struct ctld_connection *
-connection_new(struct portal *portal, int fd, const char *host,
- const struct sockaddr *client_sa)
-{
- struct ctld_connection *conn;
-
- conn = calloc(1, sizeof(*conn));
- if (conn == NULL)
- log_err(1, "calloc");
- connection_init(&conn->conn, &conn_ops, proxy_mode);
- conn->conn.conn_socket = fd;
- conn->conn_portal = portal;
- conn->conn_initiator_addr = checked_strdup(host);
- memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
-
- return (conn);
-}
-
#if 0
static void
options_print(const char *prefix, nvlist_t *nvl)
@@ -1587,16 +1620,17 @@
fprintf(stderr, "\t chap-mutual %s %s %s %s\n",
auth->a_user, auth->a_secret,
auth->a_mutual_user, auth->a_mutual_secret);
- TAILQ_FOREACH(auth_name, &ag->ag_names, an_next)
+ TAILQ_FOREACH(auth_name, &ag->ag_initiator_names, an_next)
fprintf(stderr, "\t initiator-name %s\n",
- auth_name->an_initiator_name);
- TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next)
+ auth_name->an_name);
+ TAILQ_FOREACH(auth_portal, &ag->ag_initiator_portals, ap_next)
fprintf(stderr, "\t initiator-portal %s\n",
- auth_portal->ap_initiator_portal);
+ auth_portal->ap_portal);
fprintf(stderr, "}\n");
}
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- fprintf(stderr, "portal-group %s {\n", pg->pg_name);
+ fprintf(stderr, "%s %s {\n",
+ portal_group_keyword(pg->pg_protocol), pg->pg_name);
TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
fprintf(stderr, "\t listen %s\n", portal->p_listen);
options_print("\t", pg->pg_options);
@@ -1699,7 +1733,8 @@
assert(targ->t_auth_group != NULL);
}
if (TAILQ_EMPTY(&targ->t_ports)) {
- pg = portal_group_find(conf, "default");
+ pg = portal_group_find(conf, targ->t_protocol,
+ "default");
assert(pg != NULL);
port_new(conf, targ, pg);
}
@@ -1741,8 +1776,10 @@
pg->pg_unassigned = false;
} else {
if (strcmp(pg->pg_name, "default") != 0)
- log_warnx("portal-group \"%s\" not assigned "
- "to any target", pg->pg_name);
+ log_warnx("%s \"%s\" not assigned "
+ "to any target",
+ portal_group_keyword(pg->pg_protocol),
+ pg->pg_name);
pg->pg_unassigned = true;
}
}
@@ -1808,7 +1845,7 @@
{
struct portal_group *pg = p->p_portal_group;
struct kevent kev;
- int error, sockbuf;
+ int error;
int one = 1;
log_debugx("listening on %s, portal-group \"%s\"",
@@ -1821,15 +1858,6 @@
return (false);
}
- sockbuf = SOCKBUF_SIZE;
- if (setsockopt(p->p_socket, SOL_SOCKET, SO_RCVBUF, &sockbuf,
- sizeof(sockbuf)) == -1)
- log_warn("setsockopt(SO_RCVBUF) failed for %s",
- p->p_listen);
- sockbuf = SOCKBUF_SIZE;
- if (setsockopt(p->p_socket, SOL_SOCKET, SO_SNDBUF, &sockbuf,
- sizeof(sockbuf)) == -1)
- log_warn("setsockopt(SO_SNDBUF) failed for %s", p->p_listen);
if (setsockopt(p->p_socket, SOL_SOCKET, SO_NO_DDP, &one,
sizeof(one)) == -1)
log_warn("setsockopt(SO_NO_DDP) failed for %s", p->p_listen);
@@ -1878,6 +1906,8 @@
}
}
+ pg->pg_ops->portal_init_socket(p);
+
error = bind(p->p_socket, p->p_ai->ai_addr,
p->p_ai->ai_addrlen);
if (error != 0) {
@@ -1946,11 +1976,12 @@
TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) {
if (newpg->pg_tag != 0)
continue;
- oldpg = portal_group_find(oldconf, newpg->pg_name);
+ oldpg = portal_group_find(oldconf, newpg->pg_protocol,
+ newpg->pg_name);
if (oldpg != NULL)
- newpg->pg_tag = oldpg->pg_tag;
+ newpg->pg_ops->portal_group_copy(oldpg, newpg);
else
- newpg->pg_tag = ++last_portal_group_tag;
+ newpg->pg_ops->portal_group_init(newpg);
}
/* Deregister on removed iSNS servers. */
@@ -2131,8 +2162,9 @@
if (newpg->pg_foreign)
continue;
if (newpg->pg_unassigned) {
- log_debugx("not listening on portal-group \"%s\", "
+ log_debugx("not listening on %s \"%s\", "
"not assigned to any target",
+ portal_group_keyword(newpg->pg_protocol),
newpg->pg_name);
continue;
}
@@ -2172,7 +2204,7 @@
}
#endif
assert(proxy_mode == false);
- assert(newp->p_iser == false);
+ assert(newp->p_protocol != PORTAL_PROTOCOL_ISER);
if (!portal_init_socket(newp)) {
cumulated_error++;
@@ -2188,8 +2220,10 @@
TAILQ_FOREACH(oldp, &oldpg->pg_portals, p_next) {
if (oldp->p_socket <= 0)
continue;
- log_debugx("closing socket for %s, portal-group \"%s\"",
- oldp->p_listen, oldpg->pg_name);
+ log_debugx("closing socket for %s, %s \"%s\"",
+ oldp->p_listen,
+ portal_group_keyword(oldpg->pg_protocol),
+ oldpg->pg_name);
close(oldp->p_socket);
oldp->p_socket = 0;
}
@@ -2211,7 +2245,7 @@
return (cumulated_error);
}
-static bool
+bool
timed_out(void)
{
@@ -2322,13 +2356,13 @@
handle_connection(struct portal *portal, int fd,
const struct sockaddr *client_sa, bool dont_fork)
{
- struct ctld_connection *conn;
+ struct portal_group *pg = portal->p_portal_group;
int error;
pid_t pid;
char host[NI_MAXHOST + 1];
struct conf *conf;
- conf = portal->p_portal_group->pg_conf;
+ conf = pg->pg_conf;
if (dont_fork) {
log_debugx("incoming connection; not forking due to -d flag");
@@ -2360,22 +2394,12 @@
if (error != 0)
log_errx(1, "getnameinfo: %s", gai_strerror(error));
- log_debugx("accepted connection from %s; portal group \"%s\"",
- host, portal->p_portal_group->pg_name);
+ log_debugx("accepted connection from %s; %s \"%s\"",
+ host, portal_group_keyword(pg->pg_protocol), pg->pg_name);
log_set_peer_addr(host);
setproctitle("%s", host);
- conn = connection_new(portal, fd, host, client_sa);
- set_timeout(conf->conf_timeout, true);
- kernel_capsicate();
- login(conn);
- if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
- kernel_handoff(conn);
- log_debugx("connection handed off to the kernel");
- } else {
- assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
- discovery(conn);
- }
+ pg->pg_ops->handle_connection(portal, fd, host, client_sa);
log_debugx("nothing more to do; exiting");
exit(0);
}
@@ -2564,7 +2588,7 @@
assert(ag != NULL);
ag->ag_type = AG_TYPE_DENY;
- pg = portal_group_new(conf, "default");
+ pg = portal_group_new(conf, TARGET_PROTOCOL_ISCSI, "default");
assert(pg != NULL);
if (ucl)
@@ -2590,10 +2614,10 @@
if (conf->conf_default_pg_defined == false) {
log_debugx("portal-group \"default\" not defined; "
"going with defaults");
- pg = portal_group_find(conf, "default");
+ pg = portal_group_find(conf, TARGET_PROTOCOL_ISCSI, "default");
assert(pg != NULL);
- portal_group_add_listen(pg, "0.0.0.0", false);
- portal_group_add_listen(pg, "[::]", false);
+ portal_group_add_listen(pg, "0.0.0.0", PORTAL_PROTOCOL_ISCSI);
+ portal_group_add_listen(pg, "[::]", PORTAL_PROTOCOL_ISCSI);
}
conf->conf_kernel_port_on = true;
diff --git a/usr.sbin/ctld/discovery.c b/usr.sbin/ctld/discovery.c
--- a/usr.sbin/ctld/discovery.c
+++ b/usr.sbin/ctld/discovery.c
@@ -164,14 +164,16 @@
assert(pg->pg_discovery_filter != PG_FILTER_UNKNOWN);
if (pg->pg_discovery_filter >= PG_FILTER_PORTAL &&
- auth_portal_check(ag, &conn->conn_initiator_sa) != 0) {
+ auth_portal_check(ag, TARGET_PROTOCOL_ISCSI,
+ &conn->conn_initiator_sa) != 0) {
log_debugx("initiator does not match initiator portals "
"allowed for target \"%s\"; skipping", targ->t_name);
return (true);
}
if (pg->pg_discovery_filter >= PG_FILTER_PORTAL_NAME &&
- auth_name_check(ag, conn->conn_initiator_name) != 0) {
+ auth_name_check(ag, TARGET_PROTOCOL_ISCSI,
+ conn->conn_initiator_name) != 0) {
log_debugx("initiator does not match initiator names "
"allowed for target \"%s\"; skipping", targ->t_name);
return (true);
diff --git a/usr.sbin/ctld/iscsi.c b/usr.sbin/ctld/iscsi.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/ctld/iscsi.c
@@ -0,0 +1,341 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003, 2004 Silicon Graphics International Corp.
+ * Copyright (c) 1997-2007 Kenneth D. Merry
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * Copyright (c) 2017 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * All rights reserved.
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ *
+ * Portions of this software were developed by Edward Tomasz Napierala
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libiscsiutil.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cam/ctl/ctl.h>
+#include <cam/ctl/ctl_io.h>
+#include <cam/ctl/ctl_ioctl.h>
+
+#include "ctld.h"
+
+#define SOCKBUF_SIZE 1048576
+
+#ifdef ICL_KERNEL_PROXY
+static void pdu_receive_proxy(struct pdu *pdu);
+static void pdu_send_proxy(struct pdu *pdu);
+#endif /* ICL_KERNEL_PROXY */
+static void pdu_fail(const struct connection *conn, const char *reason);
+
+static uint16_t scsi_last_portal_group_tag = 0xff;
+
+static struct connection_ops conn_ops = {
+ .timed_out = timed_out,
+#ifdef ICL_KERNEL_PROXY
+ .pdu_receive_proxy = pdu_receive_proxy,
+ .pdu_send_proxy = pdu_send_proxy,
+#endif
+ .fail = pdu_fail,
+};
+
+static void
+iscsi_portal_group_init(struct portal_group *pg)
+{
+ pg->pg_tag = ++scsi_last_portal_group_tag;
+}
+
+static void
+iscsi_portal_group_copy(struct portal_group *oldpg, struct portal_group *newpg)
+{
+ newpg->pg_tag = oldpg->pg_tag;
+}
+
+static void
+iscsi_portal_init(struct portal *p __unused)
+{
+}
+
+static void
+iscsi_portal_init_socket(struct portal *p)
+{
+ int sockbuf;
+
+ sockbuf = SOCKBUF_SIZE;
+ if (setsockopt(p->p_socket, SOL_SOCKET, SO_RCVBUF, &sockbuf,
+ sizeof(sockbuf)) == -1)
+ log_warn("setsockopt(SO_RCVBUF) failed for %s", p->p_listen);
+ sockbuf = SOCKBUF_SIZE;
+ if (setsockopt(p->p_socket, SOL_SOCKET, SO_SNDBUF, &sockbuf,
+ sizeof(sockbuf)) == -1)
+ log_warn("setsockopt(SO_SNDBUF) failed for %s", p->p_listen);
+}
+
+static void
+iscsi_portal_delete(struct portal *p __unused)
+{
+}
+
+static void
+iscsi_load_kernel_module(void)
+{
+ static bool loaded;
+ int saved_errno;
+
+ if (loaded)
+ return;
+
+ saved_errno = errno;
+ if (modfind("cfiscsi") == -1 && kldload("cfiscsi") == -1)
+ log_warn("couldn't load cfiscsi");
+ errno = saved_errno;
+ loaded = true;
+}
+
+static void
+iscsi_kernel_port_add(struct port *port, struct ctl_req *req)
+{
+ struct target *targ = port->p_target;
+ struct portal_group *pg = port->p_portal_group;
+
+ iscsi_load_kernel_module();
+
+ strlcpy(req->driver, "iscsi", sizeof(req->driver));
+
+ nvlist_add_string(req->args_nvl, "cfiscsi_target", targ->t_name);
+ nvlist_add_string(req->args_nvl, "ctld_portal_group_name", pg->pg_name);
+ nvlist_add_stringf(req->args_nvl, "cfiscsi_portal_group_tag", "%u",
+ pg->pg_tag);
+
+ if (targ->t_alias != NULL) {
+ nvlist_add_string(req->args_nvl, "cfiscsi_target_alias",
+ targ->t_alias);
+ }
+}
+
+static void
+iscsi_kernel_port_remove(struct port *port, struct ctl_req *req)
+{
+ struct target *targ = port->p_target;
+ struct portal_group *pg = port->p_portal_group;
+
+ strlcpy(req->driver, "iscsi", sizeof(req->driver));
+
+ nvlist_add_string(req->args_nvl, "cfiscsi_target", targ->t_name);
+ nvlist_add_stringf(req->args_nvl, "cfiscsi_portal_group_tag",
+ "%u", pg->pg_tag);
+}
+
+static char *
+iscsi_validate_target_name(const char *name)
+{
+ char *t_name;
+ size_t i, len;
+
+ if (valid_iscsi_name(name, log_warnx) == false) {
+ log_warnx("target name \"%s\" is invalid for iSCSI", name);
+ return (NULL);
+ }
+
+ t_name = strdup(name);
+ if (t_name == NULL) {
+ log_warn("strdup");
+ return (NULL);
+ }
+
+ /*
+ * RFC 3722 requires us to normalize the name to lowercase.
+ */
+ len = strlen(t_name);
+ for (i = 0; i < len; i++)
+ t_name[i] = tolower(t_name[i]);
+
+ return (t_name);
+}
+
+#ifdef ICL_KERNEL_PROXY
+
+static void
+pdu_receive_proxy(struct pdu *pdu)
+{
+ struct connection *conn;
+ size_t len;
+
+ assert(proxy_mode);
+ conn = pdu->pdu_connection;
+
+ kernel_receive(pdu);
+
+ len = pdu_ahs_length(pdu);
+ if (len > 0)
+ log_errx(1, "protocol error: non-empty AHS");
+
+ len = pdu_data_segment_length(pdu);
+ assert(len <= (size_t)conn->conn_max_recv_data_segment_length);
+ pdu->pdu_data_len = len;
+}
+
+static void
+pdu_send_proxy(struct pdu *pdu)
+{
+
+ assert(proxy_mode);
+
+ pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
+ kernel_send(pdu);
+}
+
+#endif /* ICL_KERNEL_PROXY */
+
+static void
+pdu_fail(const struct connection *conn __unused, const char *reason __unused)
+{
+}
+
+static struct ctld_connection *
+connection_new(struct portal *portal, int fd, const char *host,
+ const struct sockaddr *client_sa)
+{
+ struct ctld_connection *conn;
+
+ conn = calloc(1, sizeof(*conn));
+ if (conn == NULL)
+ log_err(1, "calloc");
+ connection_init(&conn->conn, &conn_ops, proxy_mode);
+ conn->conn.conn_socket = fd;
+ conn->conn_portal = portal;
+ conn->conn_initiator_addr = checked_strdup(host);
+ memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
+
+ return (conn);
+}
+
+static void
+kernel_handoff(struct ctld_connection *conn)
+{
+ struct ctl_iscsi req;
+
+ bzero(&req, sizeof(req));
+
+ req.type = CTL_ISCSI_HANDOFF;
+ strlcpy(req.data.handoff.initiator_name,
+ conn->conn_initiator_name, sizeof(req.data.handoff.initiator_name));
+ strlcpy(req.data.handoff.initiator_addr,
+ conn->conn_initiator_addr, sizeof(req.data.handoff.initiator_addr));
+ if (conn->conn_initiator_alias != NULL) {
+ strlcpy(req.data.handoff.initiator_alias,
+ conn->conn_initiator_alias, sizeof(req.data.handoff.initiator_alias));
+ }
+ memcpy(req.data.handoff.initiator_isid, conn->conn_initiator_isid,
+ sizeof(req.data.handoff.initiator_isid));
+ strlcpy(req.data.handoff.target_name,
+ conn->conn_target->t_name, sizeof(req.data.handoff.target_name));
+ if (conn->conn_portal->p_portal_group->pg_offload != NULL) {
+ strlcpy(req.data.handoff.offload,
+ conn->conn_portal->p_portal_group->pg_offload,
+ sizeof(req.data.handoff.offload));
+ }
+#ifdef ICL_KERNEL_PROXY
+ if (proxy_mode)
+ req.data.handoff.connection_id = conn->conn.conn_socket;
+ else
+ req.data.handoff.socket = conn->conn.conn_socket;
+#else
+ req.data.handoff.socket = conn->conn.conn_socket;
+#endif
+ req.data.handoff.portal_group_tag =
+ conn->conn_portal->p_portal_group->pg_tag;
+ if (conn->conn.conn_header_digest == CONN_DIGEST_CRC32C)
+ req.data.handoff.header_digest = CTL_ISCSI_DIGEST_CRC32C;
+ if (conn->conn.conn_data_digest == CONN_DIGEST_CRC32C)
+ req.data.handoff.data_digest = CTL_ISCSI_DIGEST_CRC32C;
+ req.data.handoff.cmdsn = conn->conn.conn_cmdsn;
+ req.data.handoff.statsn = conn->conn.conn_statsn;
+ req.data.handoff.max_recv_data_segment_length =
+ conn->conn.conn_max_recv_data_segment_length;
+ req.data.handoff.max_send_data_segment_length =
+ conn->conn.conn_max_send_data_segment_length;
+ req.data.handoff.max_burst_length = conn->conn.conn_max_burst_length;
+ req.data.handoff.first_burst_length =
+ conn->conn.conn_first_burst_length;
+ req.data.handoff.immediate_data = conn->conn.conn_immediate_data;
+
+ if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
+ log_err(1, "error issuing CTL_ISCSI ioctl; "
+ "dropping connection");
+ }
+
+ if (req.status != CTL_ISCSI_OK) {
+ log_errx(1, "error returned from CTL iSCSI handoff request: "
+ "%s; dropping connection", req.error_str);
+ }
+}
+
+static void
+iscsi_handle_connection(struct portal *portal, int fd, const char *host,
+ const struct sockaddr *client_sa)
+{
+ struct portal_group *pg = portal->p_portal_group;
+ struct conf *conf = pg->pg_conf;
+ struct ctld_connection *conn;
+
+ conn = connection_new(portal, fd, host, client_sa);
+ set_timeout(conf->conf_timeout, true);
+ kernel_capsicate();
+ login(conn);
+ if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+ kernel_handoff(conn);
+ log_debugx("connection handed off to the kernel");
+ } else {
+ assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
+ discovery(conn);
+ }
+}
+
+struct target_protocol_ops target_iscsi = {
+ .portal_group_init = iscsi_portal_group_init,
+ .portal_group_copy = iscsi_portal_group_copy,
+ .portal_init = iscsi_portal_init,
+ .portal_init_socket = iscsi_portal_init_socket,
+ .portal_delete = iscsi_portal_delete,
+ .kernel_port_add = iscsi_kernel_port_add,
+ .kernel_port_remove = iscsi_kernel_port_remove,
+ .validate_target_name = iscsi_validate_target_name,
+ .handle_connection = iscsi_handle_connection,
+};
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -75,9 +75,7 @@
#define NVLIST_BUFSIZE 1024
-extern bool proxy_mode;
-
-static int ctl_fd = 0;
+int ctl_fd = 0;
void
kernel_init(void)
@@ -95,14 +93,6 @@
}
if (ctl_fd < 0)
log_err(1, "failed to open %s", CTL_DEFAULT_DEV);
-#ifdef WANT_ISCSI
- else {
- saved_errno = errno;
- if (modfind("cfiscsi") == -1 && kldload("cfiscsi") == -1)
- log_warn("couldn't load cfiscsi");
- errno = saved_errno;
- }
-#endif
}
/*
@@ -409,9 +399,9 @@
struct cctl_port *port;
XML_Parser parser;
const char *key;
- char *str, *name;
+ char *str, *name, *target_name;
void *cookie;
- int error, len, retval;
+ int error, len, protocol, retval;
bzero(&devlist, sizeof(devlist));
STAILQ_INIT(&devlist.lun_list);
@@ -523,6 +513,11 @@
STAILQ_FOREACH(port, &devlist.port_list, links) {
if (strcmp(port->port_frontend, "ha") == 0)
continue;
+ if (strcmp(port->port_frontend, "iscsi") == 0)
+ protocol = TARGET_PROTOCOL_ISCSI;
+ else
+ /* XXX: Treat all unknown ports as iSCSI? */
+ protocol = TARGET_PROTOCOL_ISCSI;
free(name);
if (port->pp == 0 && port->vp == 0) {
name = checked_strdup(port->port_name);
@@ -538,7 +533,15 @@
log_err(1, "asprintf");
}
- if (port->cfiscsi_target == NULL) {
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ target_name = port->cfiscsi_target;
+ break;
+ default:
+ __assert_unreachable();
+ break;
+ }
+ if (target_name == NULL) {
log_debugx("CTL port %u \"%s\" wasn't managed by ctld; ",
port->port_id, name);
pp = pport_find(kports, name);
@@ -555,19 +558,20 @@
}
continue;
}
- if (port->cfiscsi_state != 1) {
+ if (protocol == TARGET_PROTOCOL_ISCSI &&
+ port->cfiscsi_state != 1) {
log_debugx("CTL port %ju is not active (%d); ignoring",
(uintmax_t)port->port_id, port->cfiscsi_state);
continue;
}
- targ = target_find(conf, port->cfiscsi_target);
+ targ = target_find(conf, target_name);
if (targ == NULL) {
#if 0
log_debugx("found new kernel target %s for CTL port %ld",
- port->cfiscsi_target, port->port_id);
+ target_name, port->port_id);
#endif
- targ = target_new(conf, port->cfiscsi_target);
+ targ = target_new(conf, target_name, protocol);
if (targ == NULL) {
log_warnx("target_new failed");
continue;
@@ -576,19 +580,28 @@
if (port->ctld_portal_group_name == NULL)
continue;
- pg = portal_group_find(conf, port->ctld_portal_group_name);
+ pg = portal_group_find(conf, protocol,
+ 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);
+ pg = portal_group_new(conf, protocol,
+ port->ctld_portal_group_name);
if (pg == NULL) {
log_warnx("portal_group_new failed");
continue;
}
}
- pg->pg_tag = port->cfiscsi_portal_group_tag;
+ switch (protocol) {
+ case TARGET_PROTOCOL_ISCSI:
+ pg->pg_tag = port->cfiscsi_portal_group_tag;
+ break;
+ default:
+ __assert_unreachable();
+ break;
+ }
cp = port_new(conf, targ, pg);
if (cp == NULL) {
log_warnx("port_new failed");
@@ -846,67 +859,6 @@
return (0);
}
-void
-kernel_handoff(struct ctld_connection *conn)
-{
- struct ctl_iscsi req;
-
- bzero(&req, sizeof(req));
-
- req.type = CTL_ISCSI_HANDOFF;
- strlcpy(req.data.handoff.initiator_name,
- conn->conn_initiator_name, sizeof(req.data.handoff.initiator_name));
- strlcpy(req.data.handoff.initiator_addr,
- conn->conn_initiator_addr, sizeof(req.data.handoff.initiator_addr));
- if (conn->conn_initiator_alias != NULL) {
- strlcpy(req.data.handoff.initiator_alias,
- conn->conn_initiator_alias, sizeof(req.data.handoff.initiator_alias));
- }
- memcpy(req.data.handoff.initiator_isid, conn->conn_initiator_isid,
- sizeof(req.data.handoff.initiator_isid));
- strlcpy(req.data.handoff.target_name,
- conn->conn_target->t_name, sizeof(req.data.handoff.target_name));
- if (conn->conn_portal->p_portal_group->pg_offload != NULL) {
- strlcpy(req.data.handoff.offload,
- conn->conn_portal->p_portal_group->pg_offload,
- sizeof(req.data.handoff.offload));
- }
-#ifdef ICL_KERNEL_PROXY
- if (proxy_mode)
- req.data.handoff.connection_id = conn->conn.conn_socket;
- else
- req.data.handoff.socket = conn->conn.conn_socket;
-#else
- req.data.handoff.socket = conn->conn.conn_socket;
-#endif
- req.data.handoff.portal_group_tag =
- conn->conn_portal->p_portal_group->pg_tag;
- if (conn->conn.conn_header_digest == CONN_DIGEST_CRC32C)
- req.data.handoff.header_digest = CTL_ISCSI_DIGEST_CRC32C;
- if (conn->conn.conn_data_digest == CONN_DIGEST_CRC32C)
- req.data.handoff.data_digest = CTL_ISCSI_DIGEST_CRC32C;
- req.data.handoff.cmdsn = conn->conn.conn_cmdsn;
- req.data.handoff.statsn = conn->conn.conn_statsn;
- req.data.handoff.max_recv_data_segment_length =
- conn->conn.conn_max_recv_data_segment_length;
- req.data.handoff.max_send_data_segment_length =
- conn->conn.conn_max_send_data_segment_length;
- req.data.handoff.max_burst_length = conn->conn.conn_max_burst_length;
- req.data.handoff.first_burst_length =
- conn->conn.conn_first_burst_length;
- req.data.handoff.immediate_data = conn->conn.conn_immediate_data;
-
- if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
- log_err(1, "error issuing CTL_ISCSI ioctl; "
- "dropping connection");
- }
-
- if (req.status != CTL_ISCSI_OK) {
- log_errx(1, "error returned from CTL iSCSI handoff request: "
- "%s; dropping connection", req.error_str);
- }
-}
-
int
kernel_port_add(struct port *port)
{
@@ -923,29 +875,16 @@
bzero(&req, sizeof(req));
req.reqtype = CTL_REQ_CREATE;
- if (port->p_portal_group) {
- strlcpy(req.driver, "iscsi", sizeof(req.driver));
- req.args_nvl = nvlist_clone(pg->pg_options);
- nvlist_add_string(req.args_nvl, "cfiscsi_target",
- targ->t_name);
- nvlist_add_string(req.args_nvl,
- "ctld_portal_group_name", pg->pg_name);
- nvlist_add_stringf(req.args_nvl,
- "cfiscsi_portal_group_tag", "%u", pg->pg_tag);
-
- if (targ->t_alias) {
- nvlist_add_string(req.args_nvl,
- "cfiscsi_target_alias", targ->t_alias);
- }
- }
-
if (port->p_ioctl_port) {
- strlcpy(req.driver, "ioctl", sizeof(req.driver));
req.args_nvl = nvlist_create(0);
+ strlcpy(req.driver, "ioctl", sizeof(req.driver));
nvlist_add_stringf(req.args_nvl, "pp", "%d",
port->p_ioctl_pp);
nvlist_add_stringf(req.args_nvl, "vp", "%d",
port->p_ioctl_vp);
+ } else {
+ req.args_nvl = nvlist_clone(pg->pg_options);
+ pg->pg_ops->kernel_port_add(port, &req);
}
req.args = nvlist_pack(req.args_nvl, &req.args_len);
@@ -1067,7 +1006,6 @@
struct ctl_port_entry entry;
struct ctl_lun_map lm;
struct ctl_req req;
- struct target *targ = port->p_target;
struct portal_group *pg = port->p_portal_group;
int error;
@@ -1083,22 +1021,18 @@
/* Remove iSCSI or ioctl port. */
if (port->p_portal_group || port->p_ioctl_port) {
bzero(&req, sizeof(req));
- strlcpy(req.driver, port->p_ioctl_port ? "ioctl" : "iscsi",
- sizeof(req.driver));
req.reqtype = CTL_REQ_REMOVE;
req.args_nvl = nvlist_create(0);
if (req.args_nvl == NULL)
log_err(1, "nvlist_create");
- if (port->p_ioctl_port)
+ if (port->p_ioctl_port) {
+ strlcpy(req.driver, "ioctl", sizeof(req.driver));
+
nvlist_add_stringf(req.args_nvl, "port_id", "%d",
port->p_ctl_port);
- else {
- nvlist_add_string(req.args_nvl, "cfiscsi_target",
- targ->t_name);
- nvlist_add_stringf(req.args_nvl,
- "cfiscsi_portal_group_tag", "%u", pg->pg_tag);
- }
+ } else
+ pg->pg_ops->kernel_port_remove(port, &req);
req.args = nvlist_pack(req.args_nvl, &req.args_len);
if (req.args == NULL) {
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -1027,12 +1027,13 @@
/*
* Enforce initiator-name and initiator-portal.
*/
- if (auth_name_check(ag, initiator_name) != 0) {
+ if (auth_name_check(ag, TARGET_PROTOCOL_ISCSI, initiator_name) != 0) {
login_send_error(request, 0x02, 0x02);
log_errx(1, "initiator does not match allowed initiator names");
}
- if (auth_portal_check(ag, &conn->conn_initiator_sa) != 0) {
+ if (auth_portal_check(ag, TARGET_PROTOCOL_ISCSI,
+ &conn->conn_initiator_sa) != 0) {
login_send_error(request, 0x02, 0x02);
log_errx(1, "initiator does not match allowed "
"initiator portals");
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -285,7 +285,7 @@
{
const struct auth_name *an;
- an = auth_name_new(auth_group, $2);
+ an = auth_name_new(auth_group, TARGET_PROTOCOL_ISCSI, $2);
free($2);
if (an == NULL)
return (1);
@@ -296,7 +296,7 @@
{
const struct auth_portal *ap;
- ap = auth_portal_new(auth_group, $2);
+ ap = auth_portal_new(auth_group, TARGET_PROTOCOL_ISCSI, $2);
free($2);
if (ap == NULL)
return (1);
@@ -313,15 +313,17 @@
portal_group_name: STR
{
/*
- * Make it possible to redefine default
+ * Make it possible to redefine default iSCSI
* portal-group. but only once.
*/
if (strcmp($1, "default") == 0 &&
conf->conf_default_pg_defined == false) {
- portal_group = portal_group_find(conf, $1);
+ portal_group = portal_group_find(conf,
+ TARGET_PROTOCOL_ISCSI, $1);
conf->conf_default_pg_defined = true;
} else {
- portal_group = portal_group_new(conf, $1);
+ portal_group = portal_group_new(conf,
+ TARGET_PROTOCOL_ISCSI, $1);
}
free($1);
if (portal_group == NULL)
@@ -402,7 +404,8 @@
{
int error;
- error = portal_group_add_listen(portal_group, $2, false);
+ error = portal_group_add_listen(portal_group, $2,
+ PORTAL_PROTOCOL_ISCSI);
free($2);
if (error != 0)
return (1);
@@ -413,7 +416,8 @@
{
int error;
- error = portal_group_add_listen(portal_group, $2, true);
+ error = portal_group_add_listen(portal_group, $2,
+ PORTAL_PROTOCOL_ISER);
free($2);
if (error != 0)
return (1);
@@ -555,7 +559,7 @@
target_name: STR
{
- target = target_new(conf, $1);
+ target = target_new(conf, $1, TARGET_PROTOCOL_ISCSI);
free($1);
if (target == NULL)
return (1);
@@ -741,7 +745,8 @@
}
target->t_auth_group->ag_target = target;
}
- an = auth_name_new(target->t_auth_group, $2);
+ an = auth_name_new(target->t_auth_group, TARGET_PROTOCOL_ISCSI,
+ $2);
free($2);
if (an == NULL)
return (1);
@@ -768,7 +773,8 @@
}
target->t_auth_group->ag_target = target;
}
- ap = auth_portal_new(target->t_auth_group, $2);
+ ap = auth_portal_new(target->t_auth_group,
+ TARGET_PROTOCOL_ISCSI, $2);
free($2);
if (ap == NULL)
return (1);
@@ -781,7 +787,7 @@
struct auth_group *tag;
struct port *tp;
- tpg = portal_group_find(conf, $2);
+ tpg = portal_group_find(conf, TARGET_PROTOCOL_ISCSI, $2);
if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", $2, target->t_name);
@@ -813,7 +819,7 @@
struct portal_group *tpg;
struct port *tp;
- tpg = portal_group_find(conf, $2);
+ tpg = portal_group_find(conf, TARGET_PROTOCOL_ISCSI, $2);
if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", $2, target->t_name);
diff --git a/usr.sbin/ctld/uclparse.c b/usr.sbin/ctld/uclparse.c
--- a/usr.sbin/ctld/uclparse.c
+++ b/usr.sbin/ctld/uclparse.c
@@ -156,7 +156,8 @@
}
- tpg = portal_group_find(conf, ucl_object_tostring(portal_group));
+ tpg = portal_group_find(conf, TARGET_PROTOCOL_ISCSI,
+ ucl_object_tostring(portal_group));
if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", ucl_object_tostring(portal_group), target->t_name);
@@ -464,7 +465,8 @@
while ((tmp = ucl_iterate_object(obj, &it2, true))) {
const char *value = ucl_object_tostring(tmp);
- an = auth_name_new(auth_group, value);
+ an = auth_name_new(auth_group,
+ TARGET_PROTOCOL_ISCSI, value);
if (an == NULL)
return (false);
}
@@ -482,7 +484,8 @@
while ((tmp = ucl_iterate_object(obj, &it2, true))) {
const char *value = ucl_object_tostring(tmp);
- ap = auth_portal_new(auth_group, value);
+ ap = auth_portal_new(auth_group,
+ TARGET_PROTOCOL_ISCSI, value);
if (ap == NULL)
return (false);
}
@@ -589,10 +592,12 @@
if (strcmp(name, "default") == 0 &&
conf->conf_default_pg_defined == false) {
- portal_group = portal_group_find(conf, name);
+ portal_group = portal_group_find(conf, TARGET_PROTOCOL_ISCSI,
+ name);
conf->conf_default_pg_defined = true;
} else {
- portal_group = portal_group_new(conf, name);
+ portal_group = portal_group_new(conf, TARGET_PROTOCOL_ISCSI,
+ name);
}
if (portal_group == NULL)
@@ -629,7 +634,8 @@
if (!strcmp(key, "listen")) {
if (obj->type == UCL_STRING) {
if (portal_group_add_listen(portal_group,
- ucl_object_tostring(obj), false) != 0)
+ ucl_object_tostring(obj),
+ PORTAL_PROTOCOL_ISCSI) != 0)
return (false);
} else if (obj->type == UCL_ARRAY) {
while ((tmp = ucl_iterate_object(obj, &it2,
@@ -637,7 +643,7 @@
if (portal_group_add_listen(
portal_group,
ucl_object_tostring(tmp),
- false) != 0)
+ PORTAL_PROTOCOL_ISCSI) != 0)
return (false);
}
} else {
@@ -651,7 +657,7 @@
if (!strcmp(key, "listen-iser")) {
if (obj->type == UCL_STRING) {
if (portal_group_add_listen(portal_group,
- ucl_object_tostring(obj), true) != 0)
+ ucl_object_tostring(obj), PORTAL_PROTOCOL_ISER) != 0)
return (false);
} else if (obj->type == UCL_ARRAY) {
while ((tmp = ucl_iterate_object(obj, &it2,
@@ -659,7 +665,7 @@
if (portal_group_add_listen(
portal_group,
ucl_object_tostring(tmp),
- true) != 0)
+ PORTAL_PROTOCOL_ISER) != 0)
return (false);
}
} else {
@@ -721,7 +727,7 @@
const ucl_object_t *obj = NULL, *tmp = NULL;
const char *key;
- target = target_new(conf, name);
+ target = target_new(conf, name, TARGET_PROTOCOL_ISCSI);
if (target == NULL)
return (false);
@@ -831,7 +837,7 @@
target->t_auth_group->ag_target = target;
}
an = auth_name_new(target->t_auth_group,
- ucl_object_tostring(obj));
+ TARGET_PROTOCOL_ISCSI, ucl_object_tostring(obj));
if (an == NULL)
return (false);
}
@@ -854,7 +860,7 @@
target->t_auth_group->ag_target = target;
}
ap = auth_portal_new(target->t_auth_group,
- ucl_object_tostring(obj));
+ TARGET_PROTOCOL_ISCSI, ucl_object_tostring(obj));
if (ap == NULL)
return (false);
}

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 4, 8:56 PM (14 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16460599
Default Alt Text
D48772.id150293.diff (50 KB)

Event Timeline