Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109330950
D48772.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
50 KB
Referenced Files
None
Subscribers
None
D48772.diff
View Options
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,7 +47,10 @@
#define DEFAULT_CD_BLOCKSIZE 2048
#define MAX_LUNS 1024
-#define SOCKBUF_SIZE 1048576
+
+struct ctl_req;
+struct port;
+struct target_protocol_ops;
struct auth {
TAILQ_ENTRY(auth) a_next;
@@ -61,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
@@ -85,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
@@ -103,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
@@ -117,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;
@@ -184,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 {
@@ -245,7 +288,9 @@
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);
@@ -270,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,
@@ -325,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);
@@ -352,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);
@@ -368,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,8 +75,6 @@
#define NVLIST_BUFSIZE 1024
-extern bool proxy_mode;
-
int ctl_fd = 0;
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
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 4, 4:25 PM (10 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16457384
Default Alt Text
D48772.diff (50 KB)
Attached To
Mode
D48772: ctld: Add abstractions to support multiple target protocols
Attached
Detach File
Event Timeline
Log In to Comment