aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2021-12-22 18:35:46 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2021-12-22 18:43:11 +0000
commit6378393308bc6bd81fb871dacf6b03cf1a390d8b (patch)
tree4c4868321b6903b940029e517f81c986595756b4 /usr.sbin
parentd2ef3774306c54f3999732fd02bdff39c6b4cf2a (diff)
downloadsrc-6378393308bc6bd81fb871dacf6b03cf1a390d8b.tar.gz
src-6378393308bc6bd81fb871dacf6b03cf1a390d8b.zip
Add an internal libiscsiutil library.
Move some of the code duplicated between ctld(8) and iscsid(8) into a libiscsiutil library. Sharing the low-level PDU code did require having a 'struct connection' base class with a method table to permit separate initiator vs target behavior (e.g. in handling proxy PDUs). Reviewed by: mav, emaste Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D33544
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ctld/Makefile7
-rw-r--r--usr.sbin/ctld/chap.c423
-rw-r--r--usr.sbin/ctld/ctld.c86
-rw-r--r--usr.sbin/ctld/ctld.h102
-rw-r--r--usr.sbin/ctld/discovery.c8
-rw-r--r--usr.sbin/ctld/kernel.c27
-rw-r--r--usr.sbin/ctld/keys.c199
-rw-r--r--usr.sbin/ctld/log.c202
-rw-r--r--usr.sbin/ctld/login.c51
-rw-r--r--usr.sbin/ctld/pdu.c268
-rw-r--r--usr.sbin/iscsid/Makefile5
-rw-r--r--usr.sbin/iscsid/chap.c423
-rw-r--r--usr.sbin/iscsid/discovery.c14
-rw-r--r--usr.sbin/iscsid/iscsid.c173
-rw-r--r--usr.sbin/iscsid/iscsid.h97
-rw-r--r--usr.sbin/iscsid/keys.c199
-rw-r--r--usr.sbin/iscsid/log.c202
-rw-r--r--usr.sbin/iscsid/login.c74
-rw-r--r--usr.sbin/iscsid/pdu.c309
19 files changed, 288 insertions, 2581 deletions
diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile
index ec207f024ab1..5f80ba026204 100644
--- a/usr.sbin/ctld/Makefile
+++ b/usr.sbin/ctld/Makefile
@@ -7,16 +7,17 @@ CFLAGS+=-I${SRCTOP}/contrib/libucl/include
PACKAGE= iscsi
PROG= ctld
-SRCS= chap.c ctld.c discovery.c isns.c kernel.c keys.c log.c
-SRCS+= login.c parse.y pdu.c token.l y.tab.h uclparse.c
+SRCS= ctld.c discovery.c isns.c kernel.c
+SRCS+= login.c parse.y token.l y.tab.h uclparse.c
CFLAGS+= -I${.CURDIR}
CFLAGS+= -I${SRCTOP}/sys
CFLAGS+= -I${SRCTOP}/sys/cam/ctl
CFLAGS+= -I${SRCTOP}/sys/dev/iscsi
+CFLAGS+= -I${SRCTOP}/lib/libiscsiutil
#CFLAGS+= -DICL_KERNEL_PROXY
MAN= ctld.8 ctl.conf.5
-LIBADD= bsdxml md sbuf util ucl m nv
+LIBADD= bsdxml iscsiutil md sbuf util ucl m nv
YFLAGS+= -v
CLEANFILES= y.tab.c y.tab.h y.output
diff --git a/usr.sbin/ctld/chap.c b/usr.sbin/ctld/chap.c
deleted file mode 100644
index 7b57b7080c97..000000000000
--- a/usr.sbin/ctld/chap.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2014 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <resolv.h>
-#include <md5.h>
-
-#include "ctld.h"
-
-static void
-chap_compute_md5(const char id, const char *secret,
- const void *challenge, size_t challenge_len, void *response,
- size_t response_len)
-{
- MD5_CTX ctx;
-
- assert(response_len == CHAP_DIGEST_LEN);
-
- MD5Init(&ctx);
- MD5Update(&ctx, &id, sizeof(id));
- MD5Update(&ctx, secret, strlen(secret));
- MD5Update(&ctx, challenge, challenge_len);
- MD5Final(response, &ctx);
-}
-
-static int
-chap_hex2int(const char hex)
-{
- switch (hex) {
- case '0':
- return (0x00);
- case '1':
- return (0x01);
- case '2':
- return (0x02);
- case '3':
- return (0x03);
- case '4':
- return (0x04);
- case '5':
- return (0x05);
- case '6':
- return (0x06);
- case '7':
- return (0x07);
- case '8':
- return (0x08);
- case '9':
- return (0x09);
- case 'a':
- case 'A':
- return (0x0a);
- case 'b':
- case 'B':
- return (0x0b);
- case 'c':
- case 'C':
- return (0x0c);
- case 'd':
- case 'D':
- return (0x0d);
- case 'e':
- case 'E':
- return (0x0e);
- case 'f':
- case 'F':
- return (0x0f);
- default:
- return (-1);
- }
-}
-
-static int
-chap_b642bin(const char *b64, void **binp, size_t *bin_lenp)
-{
- char *bin;
- int b64_len, bin_len;
-
- b64_len = strlen(b64);
- bin_len = (b64_len + 3) / 4 * 3;
- bin = calloc(bin_len, 1);
- if (bin == NULL)
- log_err(1, "calloc");
-
- bin_len = b64_pton(b64, bin, bin_len);
- if (bin_len < 0) {
- log_warnx("malformed base64 variable");
- free(bin);
- return (-1);
- }
- *binp = bin;
- *bin_lenp = bin_len;
- return (0);
-}
-
-/*
- * XXX: Review this _carefully_.
- */
-static int
-chap_hex2bin(const char *hex, void **binp, size_t *bin_lenp)
-{
- int i, hex_len, nibble;
- bool lo = true; /* As opposed to 'hi'. */
- char *bin;
- size_t bin_off, bin_len;
-
- if (strncasecmp(hex, "0b", strlen("0b")) == 0)
- return (chap_b642bin(hex + 2, binp, bin_lenp));
-
- if (strncasecmp(hex, "0x", strlen("0x")) != 0) {
- log_warnx("malformed variable, should start with \"0x\""
- " or \"0b\"");
- return (-1);
- }
-
- hex += strlen("0x");
- hex_len = strlen(hex);
- if (hex_len < 1) {
- log_warnx("malformed variable; doesn't contain anything "
- "but \"0x\"");
- return (-1);
- }
-
- bin_len = hex_len / 2 + hex_len % 2;
- bin = calloc(bin_len, 1);
- if (bin == NULL)
- log_err(1, "calloc");
-
- bin_off = bin_len - 1;
- for (i = hex_len - 1; i >= 0; i--) {
- nibble = chap_hex2int(hex[i]);
- if (nibble < 0) {
- log_warnx("malformed variable, invalid char \"%c\"",
- hex[i]);
- free(bin);
- return (-1);
- }
-
- assert(bin_off < bin_len);
- if (lo) {
- bin[bin_off] = nibble;
- lo = false;
- } else {
- bin[bin_off] |= nibble << 4;
- bin_off--;
- lo = true;
- }
- }
-
- *binp = bin;
- *bin_lenp = bin_len;
- return (0);
-}
-
-#ifdef USE_BASE64
-static char *
-chap_bin2hex(const char *bin, size_t bin_len)
-{
- unsigned char *b64, *tmp;
- size_t b64_len;
-
- b64_len = (bin_len + 2) / 3 * 4 + 3; /* +2 for "0b", +1 for '\0'. */
- b64 = malloc(b64_len);
- if (b64 == NULL)
- log_err(1, "malloc");
-
- tmp = b64;
- tmp += sprintf(tmp, "0b");
- b64_ntop(bin, bin_len, tmp, b64_len - 2);
-
- return (b64);
-}
-#else
-static char *
-chap_bin2hex(const char *bin, size_t bin_len)
-{
- unsigned char *hex, *tmp, ch;
- size_t hex_len;
- size_t i;
-
- hex_len = bin_len * 2 + 3; /* +2 for "0x", +1 for '\0'. */
- hex = malloc(hex_len);
- if (hex == NULL)
- log_err(1, "malloc");
-
- tmp = hex;
- tmp += sprintf(tmp, "0x");
- for (i = 0; i < bin_len; i++) {
- ch = bin[i];
- tmp += sprintf(tmp, "%02x", ch);
- }
-
- return (hex);
-}
-#endif /* !USE_BASE64 */
-
-struct chap *
-chap_new(void)
-{
- struct chap *chap;
-
- chap = calloc(1, sizeof(*chap));
- if (chap == NULL)
- log_err(1, "calloc");
-
- /*
- * Generate the challenge.
- */
- arc4random_buf(chap->chap_challenge, sizeof(chap->chap_challenge));
- arc4random_buf(&chap->chap_id, sizeof(chap->chap_id));
-
- return (chap);
-}
-
-char *
-chap_get_id(const struct chap *chap)
-{
- char *chap_i;
- int ret;
-
- ret = asprintf(&chap_i, "%d", chap->chap_id);
- if (ret < 0)
- log_err(1, "asprintf");
-
- return (chap_i);
-}
-
-char *
-chap_get_challenge(const struct chap *chap)
-{
- char *chap_c;
-
- chap_c = chap_bin2hex(chap->chap_challenge,
- sizeof(chap->chap_challenge));
-
- return (chap_c);
-}
-
-static int
-chap_receive_bin(struct chap *chap, void *response, size_t response_len)
-{
-
- if (response_len != sizeof(chap->chap_response)) {
- log_debugx("got CHAP response with invalid length; "
- "got %zd, should be %zd",
- response_len, sizeof(chap->chap_response));
- return (1);
- }
-
- memcpy(chap->chap_response, response, response_len);
- return (0);
-}
-
-int
-chap_receive(struct chap *chap, const char *response)
-{
- void *response_bin;
- size_t response_bin_len;
- int error;
-
- error = chap_hex2bin(response, &response_bin, &response_bin_len);
- if (error != 0) {
- log_debugx("got incorrectly encoded CHAP response \"%s\"",
- response);
- return (1);
- }
-
- error = chap_receive_bin(chap, response_bin, response_bin_len);
- free(response_bin);
-
- return (error);
-}
-
-int
-chap_authenticate(struct chap *chap, const char *secret)
-{
- char expected_response[CHAP_DIGEST_LEN];
-
- chap_compute_md5(chap->chap_id, secret,
- chap->chap_challenge, sizeof(chap->chap_challenge),
- expected_response, sizeof(expected_response));
-
- if (memcmp(chap->chap_response,
- expected_response, sizeof(expected_response)) != 0) {
- return (-1);
- }
-
- return (0);
-}
-
-void
-chap_delete(struct chap *chap)
-{
-
- free(chap);
-}
-
-struct rchap *
-rchap_new(const char *secret)
-{
- struct rchap *rchap;
-
- rchap = calloc(1, sizeof(*rchap));
- if (rchap == NULL)
- log_err(1, "calloc");
-
- rchap->rchap_secret = checked_strdup(secret);
-
- return (rchap);
-}
-
-static void
-rchap_receive_bin(struct rchap *rchap, const unsigned char id,
- const void *challenge, size_t challenge_len)
-{
-
- rchap->rchap_id = id;
- rchap->rchap_challenge = calloc(challenge_len, 1);
- if (rchap->rchap_challenge == NULL)
- log_err(1, "calloc");
- memcpy(rchap->rchap_challenge, challenge, challenge_len);
- rchap->rchap_challenge_len = challenge_len;
-}
-
-int
-rchap_receive(struct rchap *rchap, const char *id, const char *challenge)
-{
- unsigned char id_bin;
- void *challenge_bin;
- size_t challenge_bin_len;
-
- int error;
-
- id_bin = strtoul(id, NULL, 10);
-
- error = chap_hex2bin(challenge, &challenge_bin, &challenge_bin_len);
- if (error != 0) {
- log_debugx("got incorrectly encoded CHAP challenge \"%s\"",
- challenge);
- return (1);
- }
-
- rchap_receive_bin(rchap, id_bin, challenge_bin, challenge_bin_len);
- free(challenge_bin);
-
- return (0);
-}
-
-static void
-rchap_get_response_bin(struct rchap *rchap,
- void **responsep, size_t *response_lenp)
-{
- void *response_bin;
- size_t response_bin_len = CHAP_DIGEST_LEN;
-
- response_bin = calloc(response_bin_len, 1);
- if (response_bin == NULL)
- log_err(1, "calloc");
-
- chap_compute_md5(rchap->rchap_id, rchap->rchap_secret,
- rchap->rchap_challenge, rchap->rchap_challenge_len,
- response_bin, response_bin_len);
-
- *responsep = response_bin;
- *response_lenp = response_bin_len;
-}
-
-char *
-rchap_get_response(struct rchap *rchap)
-{
- void *response;
- size_t response_len;
- char *chap_r;
-
- rchap_get_response_bin(rchap, &response, &response_len);
- chap_r = chap_bin2hex(response, response_len);
- free(response);
-
- return (chap_r);
-}
-
-void
-rchap_delete(struct rchap *rchap)
-{
-
- free(rchap->rchap_secret);
- free(rchap->rchap_challenge);
- free(rchap);
-}
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index c37181ff00d0..3f4bca632512 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -54,6 +54,13 @@ __FBSDID("$FreeBSD$");
#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;
@@ -63,6 +70,15 @@ static volatile bool sigalrm_received = false;
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)
{
@@ -72,17 +88,6 @@ usage(void)
exit(1);
}
-char *
-checked_strdup(const char *s)
-{
- char *c;
-
- c = strdup(s);
- if (c == NULL)
- log_err(1, "strdup");
- return (c);
-}
-
struct conf *
conf_new(void)
{
@@ -1632,29 +1637,60 @@ option_set(struct option *o, const char *value)
o->o_value = checked_strdup(value);
}
-static struct connection *
+#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 connection *conn;
+ 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_socket = fd;
conn->conn_initiator_addr = checked_strdup(host);
memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
- /*
- * Default values, from RFC 3720, section 12.
- */
- conn->conn_max_recv_data_segment_length = 8192;
- conn->conn_max_send_data_segment_length = 8192;
- conn->conn_max_burst_length = 262144;
- conn->conn_first_burst_length = 65536;
- conn->conn_immediate_data = true;
-
return (conn);
}
@@ -2296,7 +2332,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
return (cumulated_error);
}
-bool
+static bool
timed_out(void)
{
@@ -2407,7 +2443,7 @@ static void
handle_connection(struct portal *portal, int fd,
const struct sockaddr *client_sa, bool dont_fork)
{
- struct connection *conn;
+ struct ctld_connection *conn;
int error;
pid_t pid;
char host[NI_MAXHOST + 1];
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
index 4ff8f0e638ac..293f5378592f 100644
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -39,6 +39,7 @@
#endif
#include <sys/socket.h>
#include <stdbool.h>
+#include <libiscsiutil.h>
#include <libutil.h>
#define DEFAULT_CONFIG_PATH "/etc/ctl.conf"
@@ -229,83 +230,25 @@ struct conf {
#define CONN_SESSION_TYPE_DISCOVERY 1
#define CONN_SESSION_TYPE_NORMAL 2
-#define CONN_DIGEST_NONE 0
-#define CONN_DIGEST_CRC32C 1
-
-struct connection {
+struct ctld_connection {
+ struct connection conn;
struct portal *conn_portal;
struct port *conn_port;
struct target *conn_target;
- int conn_socket;
int conn_session_type;
char *conn_initiator_name;
char *conn_initiator_addr;
char *conn_initiator_alias;
uint8_t conn_initiator_isid[6];
struct sockaddr_storage conn_initiator_sa;
- uint32_t conn_cmdsn;
- uint32_t conn_statsn;
int conn_max_recv_data_segment_limit;
int conn_max_send_data_segment_limit;
int conn_max_burst_limit;
int conn_first_burst_limit;
- int conn_max_recv_data_segment_length;
- int conn_max_send_data_segment_length;
- int conn_max_burst_length;
- int conn_first_burst_length;
- int conn_immediate_data;
- int conn_header_digest;
- int conn_data_digest;
const char *conn_user;
struct chap *conn_chap;
};
-struct pdu {
- struct connection *pdu_connection;
- struct iscsi_bhs *pdu_bhs;
- char *pdu_data;
- size_t pdu_data_len;
-};
-
-#define KEYS_MAX 1024
-
-struct keys {
- char *keys_names[KEYS_MAX];
- char *keys_values[KEYS_MAX];
- char *keys_data;
- size_t keys_data_len;
-};
-
-#define CHAP_CHALLENGE_LEN 1024
-#define CHAP_DIGEST_LEN 16 /* Equal to MD5 digest size. */
-
-struct chap {
- unsigned char chap_id;
- char chap_challenge[CHAP_CHALLENGE_LEN];
- char chap_response[CHAP_DIGEST_LEN];
-};
-
-struct rchap {
- char *rchap_secret;
- unsigned char rchap_id;
- void *rchap_challenge;
- size_t rchap_challenge_len;
-};
-
-struct chap *chap_new(void);
-char *chap_get_id(const struct chap *chap);
-char *chap_get_challenge(const struct chap *chap);
-int chap_receive(struct chap *chap, const char *response);
-int chap_authenticate(struct chap *chap,
- const char *secret);
-void chap_delete(struct chap *chap);
-
-struct rchap *rchap_new(const char *secret);
-int rchap_receive(struct rchap *rchap,
- const char *id, const char *challenge);
-char *rchap_get_response(struct rchap *rchap);
-void rchap_delete(struct rchap *rchap);
-
int parse_conf(struct conf *conf, const char *path);
int uclparse_conf(struct conf *conf, const char *path);
@@ -412,7 +355,7 @@ void kernel_init(void);
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 connection *conn);
+void kernel_handoff(struct ctld_connection *conn);
void kernel_limits(const char *offload,
int *max_recv_data_segment_length,
int *max_send_data_segment_length,
@@ -433,40 +376,11 @@ void kernel_send(struct pdu *pdu);
void kernel_receive(struct pdu *pdu);
#endif
-struct keys *keys_new(void);
-void keys_delete(struct keys *keys);
-void keys_load(struct keys *keys, const struct pdu *pdu);
-void keys_save(struct keys *keys, struct pdu *pdu);
-const char *keys_find(struct keys *keys, const char *name);
-void keys_add(struct keys *keys,
- const char *name, const char *value);
-void keys_add_int(struct keys *keys,
- const char *name, int value);
-
-struct pdu *pdu_new(struct connection *conn);
-struct pdu *pdu_new_response(struct pdu *request);
-void pdu_delete(struct pdu *pdu);
-void pdu_receive(struct pdu *request);
-void pdu_send(struct pdu *response);
-
-void login(struct connection *conn);
-
-void discovery(struct connection *conn);
-
-void log_init(int level);
-void log_set_peer_name(const char *name);
-void log_set_peer_addr(const char *addr);
-void log_err(int, const char *, ...)
- __dead2 __printflike(2, 3);
-void log_errx(int, const char *, ...)
- __dead2 __printflike(2, 3);
-void log_warn(const char *, ...) __printflike(1, 2);
-void log_warnx(const char *, ...) __printflike(1, 2);
-void log_debugx(const char *, ...) __printflike(1, 2);
-
-char *checked_strdup(const char *);
+void login(struct ctld_connection *conn);
+
+void discovery(struct ctld_connection *conn);
+
bool valid_iscsi_name(const char *name);
void set_timeout(int timeout, int fatal);
-bool timed_out(void);
#endif /* !CTLD_H */
diff --git a/usr.sbin/ctld/discovery.c b/usr.sbin/ctld/discovery.c
index d054aee4078c..242c5c7bca52 100644
--- a/usr.sbin/ctld/discovery.c
+++ b/usr.sbin/ctld/discovery.c
@@ -211,7 +211,7 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
}
static bool
-discovery_target_filtered_out(const struct connection *conn,
+discovery_target_filtered_out(const struct ctld_connection *conn,
const struct port *port)
{
const struct auth_group *ag;
@@ -274,7 +274,7 @@ discovery_target_filtered_out(const struct connection *conn,
}
void
-discovery(struct connection *conn)
+discovery(struct ctld_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
@@ -285,7 +285,7 @@ discovery(struct connection *conn)
pg = conn->conn_portal->p_portal_group;
log_debugx("beginning discovery session; waiting for Text PDU");
- request = text_receive(conn);
+ request = text_receive(&conn->conn);
request_keys = keys_new();
keys_load(request_keys, request);
@@ -326,7 +326,7 @@ discovery(struct connection *conn)
keys_delete(request_keys);
log_debugx("done sending targets; waiting for Logout PDU");
- request = logout_receive(conn);
+ request = logout_receive(&conn->conn);
response = logout_new_response(request);
pdu_send(response);
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index cdf2b735b54e..dbbd7c35f2d9 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -893,7 +893,7 @@ kernel_lun_remove(struct lun *lun)
}
void
-kernel_handoff(struct connection *conn)
+kernel_handoff(struct ctld_connection *conn)
{
struct ctl_iscsi req;
@@ -919,27 +919,28 @@ kernel_handoff(struct connection *conn)
}
#ifdef ICL_KERNEL_PROXY
if (proxy_mode)
- req.data.handoff.connection_id = conn->conn_socket;
+ req.data.handoff.connection_id = conn->conn.conn_socket;
else
- req.data.handoff.socket = conn->conn_socket;
+ req.data.handoff.socket = conn->conn.conn_socket;
#else
- req.data.handoff.socket = conn->conn_socket;
+ 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_header_digest == CONN_DIGEST_CRC32C)
+ if (conn->conn.conn_header_digest == CONN_DIGEST_CRC32C)
req.data.handoff.header_digest = CTL_ISCSI_DIGEST_CRC32C;
- if (conn->conn_data_digest == CONN_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_cmdsn;
- req.data.handoff.statsn = conn->conn_statsn;
+ 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_max_recv_data_segment_length;
+ conn->conn.conn_max_recv_data_segment_length;
req.data.handoff.max_send_data_segment_length =
- conn->conn_max_send_data_segment_length;
- req.data.handoff.max_burst_length = conn->conn_max_burst_length;
- req.data.handoff.first_burst_length = conn->conn_first_burst_length;
- req.data.handoff.immediate_data = conn->conn_immediate_data;
+ 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; "
diff --git a/usr.sbin/ctld/keys.c b/usr.sbin/ctld/keys.c
deleted file mode 100644
index f28e333bcd81..000000000000
--- a/usr.sbin/ctld/keys.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "ctld.h"
-
-struct keys *
-keys_new(void)
-{
- struct keys *keys;
-
- keys = calloc(1, sizeof(*keys));
- if (keys == NULL)
- log_err(1, "calloc");
-
- return (keys);
-}
-
-void
-keys_delete(struct keys *keys)
-{
-
- free(keys->keys_data);
- free(keys);
-}
-
-void
-keys_load(struct keys *keys, const struct pdu *pdu)
-{
- int i;
- char *pair;
- size_t pair_len;
-
- if (pdu->pdu_data_len == 0)
- return;
-
- if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
- log_errx(1, "protocol error: key not NULL-terminated\n");
-
- assert(keys->keys_data == NULL);
- keys->keys_data_len = pdu->pdu_data_len;
- keys->keys_data = malloc(keys->keys_data_len);
- if (keys->keys_data == NULL)
- log_err(1, "malloc");
- memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len);
-
- /*
- * XXX: Review this carefully.
- */
- pair = keys->keys_data;
- for (i = 0;; i++) {
- if (i >= KEYS_MAX)
- log_errx(1, "too many keys received");
-
- pair_len = strlen(pair);
-
- keys->keys_values[i] = pair;
- keys->keys_names[i] = strsep(&keys->keys_values[i], "=");
- if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL)
- log_errx(1, "malformed keys");
- log_debugx("key received: \"%s=%s\"",
- keys->keys_names[i], keys->keys_values[i]);
-
- pair += pair_len + 1; /* +1 to skip the terminating '\0'. */
- if (pair == keys->keys_data + keys->keys_data_len)
- break;
- assert(pair < keys->keys_data + keys->keys_data_len);
- }
-}
-
-void
-keys_save(struct keys *keys, struct pdu *pdu)
-{
- char *data;
- size_t len;
- int i;
-
- /*
- * XXX: Not particularly efficient.
- */
- len = 0;
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- break;
- /*
- * +1 for '=', +1 for '\0'.
- */
- len += strlen(keys->keys_names[i]) +
- strlen(keys->keys_values[i]) + 2;
- }
-
- if (len == 0)
- return;
-
- data = malloc(len);
- if (data == NULL)
- log_err(1, "malloc");
-
- pdu->pdu_data = data;
- pdu->pdu_data_len = len;
-
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- break;
- data += sprintf(data, "%s=%s",
- keys->keys_names[i], keys->keys_values[i]);
- data += 1; /* for '\0'. */
- }
-}
-
-const char *
-keys_find(struct keys *keys, const char *name)
-{
- int i;
-
- /*
- * Note that we don't handle duplicated key names here,
- * as they are not supposed to happen in requests, and if they do,
- * it's an initiator error.
- */
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- return (NULL);
- if (strcmp(keys->keys_names[i], name) == 0)
- return (keys->keys_values[i]);
- }
- return (NULL);
-}
-
-void
-keys_add(struct keys *keys, const char *name, const char *value)
-{
- int i;
-
- log_debugx("key to send: \"%s=%s\"", name, value);
-
- /*
- * Note that we don't check for duplicates here, as they are perfectly
- * fine in responses, e.g. the "TargetName" keys in discovery sesion
- * response.
- */
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL) {
- keys->keys_names[i] = checked_strdup(name);
- keys->keys_values[i] = checked_strdup(value);
- return;
- }
- }
- log_errx(1, "too many keys");
-}
-
-void
-keys_add_int(struct keys *keys, const char *name, int value)
-{
- char *str;
- int ret;
-
- ret = asprintf(&str, "%d", value);
- if (ret <= 0)
- log_err(1, "asprintf");
-
- keys_add(keys, name, str);
- free(str);
-}
diff --git a/usr.sbin/ctld/log.c b/usr.sbin/ctld/log.c
deleted file mode 100644
index 94e014293a61..000000000000
--- a/usr.sbin/ctld/log.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <vis.h>
-
-#include "ctld.h"
-
-static int log_level = 0;
-static char *peer_name = NULL;
-static char *peer_addr = NULL;
-
-#define MSGBUF_LEN 1024
-
-void
-log_init(int level)
-{
-
- log_level = level;
- openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
-}
-
-void
-log_set_peer_name(const char *name)
-{
-
- /*
- * XXX: Turn it into assertion?
- */
- if (peer_name != NULL)
- log_errx(1, "%s called twice", __func__);
- if (peer_addr == NULL)
- log_errx(1, "%s called before log_set_peer_addr", __func__);
-
- peer_name = checked_strdup(name);
-}
-
-void
-log_set_peer_addr(const char *addr)
-{
-
- /*
- * XXX: Turn it into assertion?
- */
- if (peer_addr != NULL)
- log_errx(1, "%s called twice", __func__);
-
- peer_addr = checked_strdup(addr);
-}
-
-static void
-log_common(int priority, int log_errno, const char *fmt, va_list ap)
-{
- static char msgbuf[MSGBUF_LEN];
- static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
- char *errstr;
- int ret;
-
- ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
- if (ret < 0) {
- fprintf(stderr, "%s: snprintf failed", getprogname());
- syslog(LOG_CRIT, "snprintf failed");
- exit(1);
- }
-
- ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL);
- if (ret < 0) {
- fprintf(stderr, "%s: strnvis failed", getprogname());
- syslog(LOG_CRIT, "strnvis failed");
- exit(1);
- }
-
- if (log_errno == -1) {
- if (peer_name != NULL) {
- fprintf(stderr, "%s: %s (%s): %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised);
- syslog(priority, "%s (%s): %s",
- peer_addr, peer_name, msgbuf_strvised);
- } else if (peer_addr != NULL) {
- fprintf(stderr, "%s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised);
- syslog(priority, "%s: %s",
- peer_addr, msgbuf_strvised);
- } else {
- fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised);
- syslog(priority, "%s", msgbuf_strvised);
- }
-
- } else {
- errstr = strerror(log_errno);
-
- if (peer_name != NULL) {
- fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised, errstr);
- syslog(priority, "%s (%s): %s: %s",
- peer_addr, peer_name, msgbuf_strvised, errstr);
- } else if (peer_addr != NULL) {
- fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised, errstr);
- syslog(priority, "%s: %s: %s",
- peer_addr, msgbuf_strvised, errstr);
- } else {
- fprintf(stderr, "%s: %s: %s\n", getprogname(),
- msgbuf_strvised, errstr);
- syslog(priority, "%s: %s",
- msgbuf_strvised, errstr);
- }
- }
-}
-
-void
-log_err(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_CRIT, errno, fmt, ap);
- va_end(ap);
-
- exit(eval);
-}
-
-void
-log_errx(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_CRIT, -1, fmt, ap);
- va_end(ap);
-
- exit(eval);
-}
-
-void
-log_warn(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_WARNING, errno, fmt, ap);
- va_end(ap);
-}
-
-void
-log_warnx(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_WARNING, -1, fmt, ap);
- va_end(ap);
-}
-
-void
-log_debugx(const char *fmt, ...)
-{
- va_list ap;
-
- if (log_level == 0)
- return;
-
- va_start(ap, fmt);
- log_common(LOG_DEBUG, -1, fmt, ap);
- va_end(ap);
-}
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
index 63b2cfd51d92..da69961e40ae 100644
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -401,7 +401,7 @@ login_send_chap_success(struct pdu *request,
}
static void
-login_chap(struct connection *conn, struct auth_group *ag)
+login_chap(struct ctld_connection *conn, struct auth_group *ag)
{
const struct auth *auth;
struct chap *chap;
@@ -411,7 +411,7 @@ login_chap(struct connection *conn, struct auth_group *ag)
* Receive CHAP_A PDU.
*/
log_debugx("beginning CHAP authentication; waiting for CHAP_A");
- request = login_receive_chap_a(conn);
+ request = login_receive_chap_a(&conn->conn);
/*
* Generate the challenge.
@@ -430,7 +430,7 @@ login_chap(struct connection *conn, struct auth_group *ag)
* Receive CHAP_N/CHAP_R PDU and authenticate.
*/
log_debugx("waiting for CHAP_N/CHAP_R");
- request = login_receive_chap_r(conn, ag, chap, &auth);
+ request = login_receive_chap_r(&conn->conn, ag, chap, &auth);
/*
* Yay, authentication succeeded!
@@ -453,9 +453,9 @@ login_negotiate_key(struct pdu *request, const char *name,
{
int which;
size_t tmp;
- struct connection *conn;
+ struct ctld_connection *conn;
- conn = request->pdu_connection;
+ conn = (struct ctld_connection *)request->pdu_connection;
if (strcmp(name, "InitiatorName") == 0) {
if (!skipped_security)
@@ -487,7 +487,7 @@ login_negotiate_key(struct pdu *request, const char *name,
case 1:
log_debugx("initiator prefers CRC32C "
"for header digest; we'll use it");
- conn->conn_header_digest = CONN_DIGEST_CRC32C;
+ conn->conn.conn_header_digest = CONN_DIGEST_CRC32C;
keys_add(response_keys, name, "CRC32C");
break;
case 2:
@@ -513,7 +513,7 @@ login_negotiate_key(struct pdu *request, const char *name,
case 1:
log_debugx("initiator prefers CRC32C "
"for data digest; we'll use it");
- conn->conn_data_digest = CONN_DIGEST_CRC32C;
+ conn->conn.conn_data_digest = CONN_DIGEST_CRC32C;
keys_add(response_keys, name, "CRC32C");
break;
case 2:
@@ -537,10 +537,10 @@ login_negotiate_key(struct pdu *request, const char *name,
keys_add(response_keys, name, "Irrelevant");
} else {
if (strcmp(value, "Yes") == 0) {
- conn->conn_immediate_data = true;
+ conn->conn.conn_immediate_data = true;
keys_add(response_keys, name, "Yes");
} else {
- conn->conn_immediate_data = false;
+ conn->conn.conn_immediate_data = false;
keys_add(response_keys, name, "No");
}
}
@@ -564,7 +564,7 @@ login_negotiate_key(struct pdu *request, const char *name,
conn->conn_max_send_data_segment_limit);
tmp = conn->conn_max_send_data_segment_limit;
}
- conn->conn_max_send_data_segment_length = tmp;
+ conn->conn.conn_max_send_data_segment_length = tmp;
} else if (strcmp(name, "MaxBurstLength") == 0) {
tmp = strtoul(value, NULL, 10);
if (tmp <= 0) {
@@ -576,7 +576,7 @@ login_negotiate_key(struct pdu *request, const char *name,
tmp, conn->conn_max_burst_limit);
tmp = conn->conn_max_burst_limit;
}
- conn->conn_max_burst_length = tmp;
+ conn->conn.conn_max_burst_length = tmp;
keys_add_int(response_keys, name, tmp);
} else if (strcmp(name, "FirstBurstLength") == 0) {
tmp = strtoul(value, NULL, 10);
@@ -589,7 +589,7 @@ login_negotiate_key(struct pdu *request, const char *name,
tmp, conn->conn_first_burst_limit);
tmp = conn->conn_first_burst_limit;
}
- conn->conn_first_burst_length = tmp;
+ conn->conn.conn_first_burst_length = tmp;
keys_add_int(response_keys, name, tmp);
} else if (strcmp(name, "DefaultTime2Wait") == 0) {
keys_add(response_keys, name, value);
@@ -642,7 +642,7 @@ login_redirect(struct pdu *request, const char *target_address)
}
static bool
-login_portal_redirect(struct connection *conn, struct pdu *request)
+login_portal_redirect(struct ctld_connection *conn, struct pdu *request)
{
const struct portal_group *pg;
@@ -658,7 +658,7 @@ login_portal_redirect(struct connection *conn, struct pdu *request)
}
static bool
-login_target_redirect(struct connection *conn, struct pdu *request)
+login_target_redirect(struct ctld_connection *conn, struct pdu *request)
{
const char *target_address;
@@ -679,7 +679,7 @@ login_target_redirect(struct connection *conn, struct pdu *request)
}
static void
-login_negotiate(struct connection *conn, struct pdu *request)
+login_negotiate(struct ctld_connection *conn, struct pdu *request)
{
struct pdu *response;
struct iscsi_bhs_login_response *bhslr2;
@@ -721,8 +721,8 @@ login_negotiate(struct connection *conn, struct pdu *request)
* sender and receiver operation, and we must obey defaults.
*/
if (conn->conn_max_send_data_segment_limit <
- conn->conn_max_send_data_segment_length) {
- conn->conn_max_send_data_segment_length =
+ conn->conn.conn_max_send_data_segment_length) {
+ conn->conn.conn_max_send_data_segment_length =
conn->conn_max_send_data_segment_limit;
}
} else {
@@ -735,7 +735,7 @@ login_negotiate(struct connection *conn, struct pdu *request)
if (request == NULL) {
log_debugx("beginning operational parameter negotiation; "
"waiting for Login PDU");
- request = login_receive(conn, false);
+ request = login_receive(&conn->conn, false);
skipped_security = false;
} else
skipped_security = true;
@@ -788,14 +788,15 @@ login_negotiate(struct connection *conn, struct pdu *request)
* with illegal values here.
*/
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL &&
- conn->conn_first_burst_length > conn->conn_max_burst_length) {
+ conn->conn.conn_first_burst_length >
+ conn->conn.conn_max_burst_length) {
log_errx(1, "initiator sent FirstBurstLength > MaxBurstLength");
}
- conn->conn_max_recv_data_segment_length =
+ conn->conn.conn_max_recv_data_segment_length =
conn->conn_max_recv_data_segment_limit;
keys_add_int(response_keys, "MaxRecvDataSegmentLength",
- conn->conn_max_recv_data_segment_length);
+ conn->conn.conn_max_recv_data_segment_length);
log_debugx("operational parameter negotiation done; "
"transitioning to Full Feature Phase");
@@ -809,13 +810,13 @@ login_negotiate(struct connection *conn, struct pdu *request)
}
static void
-login_wait_transition(struct connection *conn)
+login_wait_transition(struct ctld_connection *conn)
{
struct pdu *request, *response;
struct iscsi_bhs_login_request *bhslr;
log_debugx("waiting for state transition request");
- request = login_receive(conn, false);
+ request = login_receive(&conn->conn, false);
bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0) {
login_send_error(request, 0x02, 0x00);
@@ -833,7 +834,7 @@ login_wait_transition(struct connection *conn)
}
void
-login(struct connection *conn)
+login(struct ctld_connection *conn)
{
struct pdu *request, *response;
struct iscsi_bhs_login_request *bhslr;
@@ -850,7 +851,7 @@ login(struct connection *conn)
* is required, or call appropriate authentication code.
*/
log_debugx("beginning Login Phase; waiting for Login PDU");
- request = login_receive(conn, true);
+ request = login_receive(&conn->conn, true);
bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
if (bhslr->bhslr_tsih != 0) {
login_send_error(request, 0x02, 0x0a);
diff --git a/usr.sbin/ctld/pdu.c b/usr.sbin/ctld/pdu.c
deleted file mode 100644
index 04691556b997..000000000000
--- a/usr.sbin/ctld/pdu.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "ctld.h"
-#include "iscsi_proto.h"
-
-#ifdef ICL_KERNEL_PROXY
-#include <sys/ioctl.h>
-#endif
-
-extern bool proxy_mode;
-
-static int
-pdu_ahs_length(const struct pdu *pdu)
-{
-
- return (pdu->pdu_bhs->bhs_total_ahs_len * 4);
-}
-
-static int
-pdu_data_segment_length(const struct pdu *pdu)
-{
- uint32_t len = 0;
-
- len += pdu->pdu_bhs->bhs_data_segment_len[0];
- len <<= 8;
- len += pdu->pdu_bhs->bhs_data_segment_len[1];
- len <<= 8;
- len += pdu->pdu_bhs->bhs_data_segment_len[2];
-
- return (len);
-}
-
-static void
-pdu_set_data_segment_length(struct pdu *pdu, uint32_t len)
-{
-
- pdu->pdu_bhs->bhs_data_segment_len[2] = len;
- pdu->pdu_bhs->bhs_data_segment_len[1] = len >> 8;
- pdu->pdu_bhs->bhs_data_segment_len[0] = len >> 16;
-}
-
-struct pdu *
-pdu_new(struct connection *conn)
-{
- struct pdu *pdu;
-
- pdu = calloc(1, sizeof(*pdu));
- if (pdu == NULL)
- log_err(1, "calloc");
-
- pdu->pdu_bhs = calloc(1, sizeof(*pdu->pdu_bhs));
- if (pdu->pdu_bhs == NULL)
- log_err(1, "calloc");
-
- pdu->pdu_connection = conn;
-
- return (pdu);
-}
-
-struct pdu *
-pdu_new_response(struct pdu *request)
-{
-
- return (pdu_new(request->pdu_connection));
-}
-
-#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 size_t
-pdu_padding(const struct pdu *pdu)
-{
-
- if ((pdu->pdu_data_len % 4) != 0)
- return (4 - (pdu->pdu_data_len % 4));
-
- return (0);
-}
-
-static void
-pdu_read(int fd, char *data, size_t len)
-{
- ssize_t ret;
-
- while (len > 0) {
- ret = read(fd, data, len);
- if (ret < 0) {
- if (timed_out())
- log_errx(1, "exiting due to timeout");
- log_err(1, "read");
- } else if (ret == 0)
- log_errx(1, "read: connection lost");
- len -= ret;
- data += ret;
- }
-}
-
-void
-pdu_receive(struct pdu *pdu)
-{
- struct connection *conn;
- size_t len, padding;
- char dummy[4];
-
-#ifdef ICL_KERNEL_PROXY
- if (proxy_mode)
- return (pdu_receive_proxy(pdu));
-#endif
-
- assert(proxy_mode == false);
- conn = pdu->pdu_connection;
-
- pdu_read(conn->conn_socket, (char *)pdu->pdu_bhs,
- sizeof(*pdu->pdu_bhs));
-
- len = pdu_ahs_length(pdu);
- if (len > 0)
- log_errx(1, "protocol error: non-empty AHS");
-
- len = pdu_data_segment_length(pdu);
- if (len > 0) {
- if (len > (size_t)conn->conn_max_recv_data_segment_length) {
- log_errx(1, "protocol error: received PDU "
- "with DataSegmentLength exceeding %d",
- conn->conn_max_recv_data_segment_length);
- }
-
- pdu->pdu_data_len = len;
- pdu->pdu_data = malloc(len);
- if (pdu->pdu_data == NULL)
- log_err(1, "malloc");
-
- pdu_read(conn->conn_socket, (char *)pdu->pdu_data,
- pdu->pdu_data_len);
-
- padding = pdu_padding(pdu);
- if (padding != 0) {
- assert(padding < sizeof(dummy));
- pdu_read(conn->conn_socket, (char *)dummy, padding);
- }
- }
-}
-
-void
-pdu_send(struct pdu *pdu)
-{
- ssize_t ret, total_len;
- size_t padding;
- uint32_t zero = 0;
- struct iovec iov[3];
- int iovcnt;
-
-#ifdef ICL_KERNEL_PROXY
- if (proxy_mode)
- return (pdu_send_proxy(pdu));
-#endif
-
- assert(proxy_mode == false);
-
- pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
- iov[0].iov_base = pdu->pdu_bhs;
- iov[0].iov_len = sizeof(*pdu->pdu_bhs);
- total_len = iov[0].iov_len;
- iovcnt = 1;
-
- if (pdu->pdu_data_len > 0) {
- iov[1].iov_base = pdu->pdu_data;
- iov[1].iov_len = pdu->pdu_data_len;
- total_len += iov[1].iov_len;
- iovcnt = 2;
-
- padding = pdu_padding(pdu);
- if (padding > 0) {
- assert(padding < sizeof(zero));
- iov[2].iov_base = &zero;
- iov[2].iov_len = padding;
- total_len += iov[2].iov_len;
- iovcnt = 3;
- }
- }
-
- ret = writev(pdu->pdu_connection->conn_socket, iov, iovcnt);
- if (ret < 0) {
- if (timed_out())
- log_errx(1, "exiting due to timeout");
- log_err(1, "writev");
- }
- if (ret != total_len)
- log_errx(1, "short write");
-}
-
-void
-pdu_delete(struct pdu *pdu)
-{
-
- free(pdu->pdu_data);
- free(pdu->pdu_bhs);
- free(pdu);
-}
diff --git a/usr.sbin/iscsid/Makefile b/usr.sbin/iscsid/Makefile
index e3b1acb636b2..f9694866b7f6 100644
--- a/usr.sbin/iscsid/Makefile
+++ b/usr.sbin/iscsid/Makefile
@@ -2,13 +2,14 @@
PACKAGE= iscsi
PROG= iscsid
-SRCS= chap.c discovery.c iscsid.c keys.c log.c login.c pdu.c
+SRCS= discovery.c iscsid.c login.c
CFLAGS+= -I${.CURDIR}
CFLAGS+= -I${SRCTOP}/sys/cam
CFLAGS+= -I${SRCTOP}/sys/dev/iscsi
+CFLAGS+= -I${SRCTOP}/lib/libiscsiutil
CFLAGS+= -DICL_KERNEL_PROXY
MAN= iscsid.8
-LIBADD= md util
+LIBADD= iscsiutil md util
.include <bsd.prog.mk>
diff --git a/usr.sbin/iscsid/chap.c b/usr.sbin/iscsid/chap.c
deleted file mode 100644
index bbedfd77fb0f..000000000000
--- a/usr.sbin/iscsid/chap.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2014 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <resolv.h>
-#include <md5.h>
-
-#include "iscsid.h"
-
-static void
-chap_compute_md5(const char id, const char *secret,
- const void *challenge, size_t challenge_len, void *response,
- size_t response_len)
-{
- MD5_CTX ctx;
-
- assert(response_len == CHAP_DIGEST_LEN);
-
- MD5Init(&ctx);
- MD5Update(&ctx, &id, sizeof(id));
- MD5Update(&ctx, secret, strlen(secret));
- MD5Update(&ctx, challenge, challenge_len);
- MD5Final(response, &ctx);
-}
-
-static int
-chap_hex2int(const char hex)
-{
- switch (hex) {
- case '0':
- return (0x00);
- case '1':
- return (0x01);
- case '2':
- return (0x02);
- case '3':
- return (0x03);
- case '4':
- return (0x04);
- case '5':
- return (0x05);
- case '6':
- return (0x06);
- case '7':
- return (0x07);
- case '8':
- return (0x08);
- case '9':
- return (0x09);
- case 'a':
- case 'A':
- return (0x0a);
- case 'b':
- case 'B':
- return (0x0b);
- case 'c':
- case 'C':
- return (0x0c);
- case 'd':
- case 'D':
- return (0x0d);
- case 'e':
- case 'E':
- return (0x0e);
- case 'f':
- case 'F':
- return (0x0f);
- default:
- return (-1);
- }
-}
-
-static int
-chap_b642bin(const char *b64, void **binp, size_t *bin_lenp)
-{
- char *bin;
- int b64_len, bin_len;
-
- b64_len = strlen(b64);
- bin_len = (b64_len + 3) / 4 * 3;
- bin = calloc(bin_len, 1);
- if (bin == NULL)
- log_err(1, "calloc");
-
- bin_len = b64_pton(b64, bin, bin_len);
- if (bin_len < 0) {
- log_warnx("malformed base64 variable");
- free(bin);
- return (-1);
- }
- *binp = bin;
- *bin_lenp = bin_len;
- return (0);
-}
-
-/*
- * XXX: Review this _carefully_.
- */
-static int
-chap_hex2bin(const char *hex, void **binp, size_t *bin_lenp)
-{
- int i, hex_len, nibble;
- bool lo = true; /* As opposed to 'hi'. */
- char *bin;
- size_t bin_off, bin_len;
-
- if (strncasecmp(hex, "0b", strlen("0b")) == 0)
- return (chap_b642bin(hex + 2, binp, bin_lenp));
-
- if (strncasecmp(hex, "0x", strlen("0x")) != 0) {
- log_warnx("malformed variable, should start with \"0x\""
- " or \"0b\"");
- return (-1);
- }
-
- hex += strlen("0x");
- hex_len = strlen(hex);
- if (hex_len < 1) {
- log_warnx("malformed variable; doesn't contain anything "
- "but \"0x\"");
- return (-1);
- }
-
- bin_len = hex_len / 2 + hex_len % 2;
- bin = calloc(bin_len, 1);
- if (bin == NULL)
- log_err(1, "calloc");
-
- bin_off = bin_len - 1;
- for (i = hex_len - 1; i >= 0; i--) {
- nibble = chap_hex2int(hex[i]);
- if (nibble < 0) {
- log_warnx("malformed variable, invalid char \"%c\"",
- hex[i]);
- free(bin);
- return (-1);
- }
-
- assert(bin_off < bin_len);
- if (lo) {
- bin[bin_off] = nibble;
- lo = false;
- } else {
- bin[bin_off] |= nibble << 4;
- bin_off--;
- lo = true;
- }
- }
-
- *binp = bin;
- *bin_lenp = bin_len;
- return (0);
-}
-
-#ifdef USE_BASE64
-static char *
-chap_bin2hex(const char *bin, size_t bin_len)
-{
- unsigned char *b64, *tmp;
- size_t b64_len;
-
- b64_len = (bin_len + 2) / 3 * 4 + 3; /* +2 for "0b", +1 for '\0'. */
- b64 = malloc(b64_len);
- if (b64 == NULL)
- log_err(1, "malloc");
-
- tmp = b64;
- tmp += sprintf(tmp, "0b");
- b64_ntop(bin, bin_len, tmp, b64_len - 2);
-
- return (b64);
-}
-#else
-static char *
-chap_bin2hex(const char *bin, size_t bin_len)
-{
- unsigned char *hex, *tmp, ch;
- size_t hex_len;
- size_t i;
-
- hex_len = bin_len * 2 + 3; /* +2 for "0x", +1 for '\0'. */
- hex = malloc(hex_len);
- if (hex == NULL)
- log_err(1, "malloc");
-
- tmp = hex;
- tmp += sprintf(tmp, "0x");
- for (i = 0; i < bin_len; i++) {
- ch = bin[i];
- tmp += sprintf(tmp, "%02x", ch);
- }
-
- return (hex);
-}
-#endif /* !USE_BASE64 */
-
-struct chap *
-chap_new(void)
-{
- struct chap *chap;
-
- chap = calloc(1, sizeof(*chap));
- if (chap == NULL)
- log_err(1, "calloc");
-
- /*
- * Generate the challenge.
- */
- arc4random_buf(chap->chap_challenge, sizeof(chap->chap_challenge));
- arc4random_buf(&chap->chap_id, sizeof(chap->chap_id));
-
- return (chap);
-}
-
-char *
-chap_get_id(const struct chap *chap)
-{
- char *chap_i;
- int ret;
-
- ret = asprintf(&chap_i, "%d", chap->chap_id);
- if (ret < 0)
- log_err(1, "asprintf");
-
- return (chap_i);
-}
-
-char *
-chap_get_challenge(const struct chap *chap)
-{
- char *chap_c;
-
- chap_c = chap_bin2hex(chap->chap_challenge,
- sizeof(chap->chap_challenge));
-
- return (chap_c);
-}
-
-static int
-chap_receive_bin(struct chap *chap, void *response, size_t response_len)
-{
-
- if (response_len != sizeof(chap->chap_response)) {
- log_debugx("got CHAP response with invalid length; "
- "got %zd, should be %zd",
- response_len, sizeof(chap->chap_response));
- return (1);
- }
-
- memcpy(chap->chap_response, response, response_len);
- return (0);
-}
-
-int
-chap_receive(struct chap *chap, const char *response)
-{
- void *response_bin;
- size_t response_bin_len;
- int error;
-
- error = chap_hex2bin(response, &response_bin, &response_bin_len);
- if (error != 0) {
- log_debugx("got incorrectly encoded CHAP response \"%s\"",
- response);
- return (1);
- }
-
- error = chap_receive_bin(chap, response_bin, response_bin_len);
- free(response_bin);
-
- return (error);
-}
-
-int
-chap_authenticate(struct chap *chap, const char *secret)
-{
- char expected_response[CHAP_DIGEST_LEN];
-
- chap_compute_md5(chap->chap_id, secret,
- chap->chap_challenge, sizeof(chap->chap_challenge),
- expected_response, sizeof(expected_response));
-
- if (memcmp(chap->chap_response,
- expected_response, sizeof(expected_response)) != 0) {
- return (-1);
- }
-
- return (0);
-}
-
-void
-chap_delete(struct chap *chap)
-{
-
- free(chap);
-}
-
-struct rchap *
-rchap_new(const char *secret)
-{
- struct rchap *rchap;
-
- rchap = calloc(1, sizeof(*rchap));
- if (rchap == NULL)
- log_err(1, "calloc");
-
- rchap->rchap_secret = checked_strdup(secret);
-
- return (rchap);
-}
-
-static void
-rchap_receive_bin(struct rchap *rchap, const unsigned char id,
- const void *challenge, size_t challenge_len)
-{
-
- rchap->rchap_id = id;
- rchap->rchap_challenge = calloc(challenge_len, 1);
- if (rchap->rchap_challenge == NULL)
- log_err(1, "calloc");
- memcpy(rchap->rchap_challenge, challenge, challenge_len);
- rchap->rchap_challenge_len = challenge_len;
-}
-
-int
-rchap_receive(struct rchap *rchap, const char *id, const char *challenge)
-{
- unsigned char id_bin;
- void *challenge_bin;
- size_t challenge_bin_len;
-
- int error;
-
- id_bin = strtoul(id, NULL, 10);
-
- error = chap_hex2bin(challenge, &challenge_bin, &challenge_bin_len);
- if (error != 0) {
- log_debugx("got incorrectly encoded CHAP challenge \"%s\"",
- challenge);
- return (1);
- }
-
- rchap_receive_bin(rchap, id_bin, challenge_bin, challenge_bin_len);
- free(challenge_bin);
-
- return (0);
-}
-
-static void
-rchap_get_response_bin(struct rchap *rchap,
- void **responsep, size_t *response_lenp)
-{
- void *response_bin;
- size_t response_bin_len = CHAP_DIGEST_LEN;
-
- response_bin = calloc(response_bin_len, 1);
- if (response_bin == NULL)
- log_err(1, "calloc");
-
- chap_compute_md5(rchap->rchap_id, rchap->rchap_secret,
- rchap->rchap_challenge, rchap->rchap_challenge_len,
- response_bin, response_bin_len);
-
- *responsep = response_bin;
- *response_lenp = response_bin_len;
-}
-
-char *
-rchap_get_response(struct rchap *rchap)
-{
- void *response;
- size_t response_len;
- char *chap_r;
-
- rchap_get_response_bin(rchap, &response, &response_len);
- chap_r = chap_bin2hex(response, response_len);
- free(response);
-
- return (chap_r);
-}
-
-void
-rchap_delete(struct rchap *rchap)
-{
-
- free(rchap->rchap_secret);
- free(rchap->rchap_challenge);
- free(rchap);
-}
diff --git a/usr.sbin/iscsid/discovery.c b/usr.sbin/iscsid/discovery.c
index 801b5c96a441..c60c77307a55 100644
--- a/usr.sbin/iscsid/discovery.c
+++ b/usr.sbin/iscsid/discovery.c
@@ -138,7 +138,7 @@ logout_new_request(struct connection *conn)
}
static void
-kernel_add(const struct connection *conn, const char *target)
+kernel_add(const struct iscsid_connection *conn, const char *target)
{
struct iscsi_session_add isa;
int error;
@@ -154,7 +154,7 @@ kernel_add(const struct connection *conn, const char *target)
}
static void
-kernel_remove(const struct connection *conn)
+kernel_remove(const struct iscsid_connection *conn)
{
struct iscsi_session_remove isr;
int error;
@@ -167,14 +167,14 @@ kernel_remove(const struct connection *conn)
}
void
-discovery(struct connection *conn)
+discovery(struct iscsid_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
int i;
log_debugx("beginning discovery session");
- request = text_new_request(conn);
+ request = text_new_request(&conn->conn);
request_keys = keys_new();
keys_add(request_keys, "SendTargets", "All");
keys_save(request_keys, request);
@@ -185,7 +185,7 @@ discovery(struct connection *conn)
request = NULL;
log_debugx("waiting for Text Response");
- response = text_receive(conn);
+ response = text_receive(&conn->conn);
response_keys = keys_new();
keys_load(response_keys, response);
for (i = 0; i < KEYS_MAX; i++) {
@@ -220,13 +220,13 @@ discovery(struct connection *conn)
#endif
log_debugx("discovery done; logging out");
- request = logout_new_request(conn);
+ request = logout_new_request(&conn->conn);
pdu_send(request);
pdu_delete(request);
request = NULL;
log_debugx("waiting for Logout Response");
- response = logout_receive(conn);
+ response = logout_receive(&conn->conn);
pdu_delete(response);
log_debugx("discovery session done");
diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
index db8b5d4f5e4c..dc28a4f6f0cb 100644
--- a/usr.sbin/iscsid/iscsid.c
+++ b/usr.sbin/iscsid/iscsid.c
@@ -57,10 +57,25 @@ __FBSDID("$FreeBSD$");
#include "iscsid.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 volatile bool sigalrm_received = false;
static int nchildren = 0;
+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 = fail,
+};
+
static void
usage(void)
{
@@ -69,17 +84,67 @@ usage(void)
exit(1);
}
-char *
-checked_strdup(const char *s)
+#ifdef ICL_KERNEL_PROXY
+
+static void
+pdu_receive_proxy(struct pdu *pdu)
+{
+ struct iscsid_connection *conn;
+ struct iscsi_daemon_receive idr;
+ size_t len;
+ int error;
+
+ conn = (struct iscsid_connection *)pdu->pdu_connection;
+ assert(conn->conn_conf.isc_iser != 0);
+
+ pdu->pdu_data = malloc(conn->conn.conn_max_recv_data_segment_length);
+ if (pdu->pdu_data == NULL)
+ log_err(1, "malloc");
+
+ memset(&idr, 0, sizeof(idr));
+ idr.idr_session_id = conn->conn_session_id;
+ idr.idr_bhs = pdu->pdu_bhs;
+ idr.idr_data_segment_len = conn->conn.conn_max_recv_data_segment_length;
+ idr.idr_data_segment = pdu->pdu_data;
+
+ error = ioctl(conn->conn_iscsi_fd, ISCSIDRECEIVE, &idr);
+ if (error != 0)
+ log_err(1, "ISCSIDRECEIVE");
+
+ 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.conn_max_recv_data_segment_length);
+ pdu->pdu_data_len = len;
+}
+
+static void
+pdu_send_proxy(struct pdu *pdu)
{
- char *c;
+ struct iscsid_connection *conn;
+ struct iscsi_daemon_send ids;
+ int error;
+
+ conn = (struct iscsid_connection *)pdu->pdu_connection;
+ assert(conn->conn_conf.isc_iser != 0);
- c = strdup(s);
- if (c == NULL)
- log_err(1, "strdup");
- return (c);
+ pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
+
+ memset(&ids, 0, sizeof(ids));
+ ids.ids_session_id = conn->conn_session_id;
+ ids.ids_bhs = pdu->pdu_bhs;
+ ids.ids_data_segment_len = pdu->pdu_data_len;
+ ids.ids_data_segment = pdu->pdu_data;
+
+ error = ioctl(conn->conn_iscsi_fd, ISCSIDSEND, &ids);
+ if (error != 0)
+ log_err(1, "ISCSIDSEND");
}
+#endif /* ICL_KERNEL_PROXY */
+
static void
resolve_addr(const struct connection *conn, const char *address,
struct addrinfo **ai, bool initiator_side)
@@ -154,10 +219,10 @@ resolve_addr(const struct connection *conn, const char *address,
free(addr);
}
-static struct connection *
+static struct iscsid_connection *
connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
{
- struct connection *conn;
+ struct iscsid_connection *conn;
struct iscsi_session_limits *isl;
struct addrinfo *from_ai, *to_ai;
const char *from_addr, *to_addr;
@@ -170,24 +235,17 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
if (conn == NULL)
log_err(1, "calloc");
- /*
- * Default values, from RFC 3720, section 12.
- */
+ connection_init(&conn->conn, &conn_ops,
+ request->idr_conf.isc_iser != 0);
conn->conn_protocol_level = 0;
- conn->conn_header_digest = CONN_DIGEST_NONE;
- conn->conn_data_digest = CONN_DIGEST_NONE;
conn->conn_initial_r2t = true;
- conn->conn_immediate_data = true;
- conn->conn_max_recv_data_segment_length = 8192;
- conn->conn_max_send_data_segment_length = 8192;
- conn->conn_max_burst_length = 262144;
- conn->conn_first_burst_length = 65536;
conn->conn_iscsi_fd = iscsi_fd;
conn->conn_session_id = request->idr_session_id;
memcpy(&conn->conn_conf, &request->idr_conf, sizeof(conn->conn_conf));
- memcpy(&conn->conn_isid, &request->idr_isid, sizeof(conn->conn_isid));
- conn->conn_tsih = request->idr_tsih;
+ memcpy(&conn->conn.conn_isid, &request->idr_isid,
+ sizeof(conn->conn.conn_isid));
+ conn->conn.conn_tsih = request->idr_tsih;
/*
* Read the driver limits and provide reasonable defaults for the ones
@@ -215,9 +273,9 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
* We can't do it for other limits, since they may affect both
* sender and receiver operation, and we must obey defaults.
*/
- if (conn->conn_max_send_data_segment_length >
+ if (conn->conn.conn_max_send_data_segment_length >
isl->isl_max_send_data_segment_length) {
- conn->conn_max_send_data_segment_length =
+ conn->conn.conn_max_send_data_segment_length =
isl->isl_max_send_data_segment_length;
}
@@ -225,11 +283,11 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
to_addr = conn->conn_conf.isc_target_addr;
if (from_addr[0] != '\0')
- resolve_addr(conn, from_addr, &from_ai, true);
+ resolve_addr(&conn->conn, from_addr, &from_ai, true);
else
from_ai = NULL;
- resolve_addr(conn, to_addr, &to_ai, false);
+ resolve_addr(&conn->conn, to_addr, &to_ai, false);
#ifdef ICL_KERNEL_PROXY
if (conn->conn_conf.isc_iser) {
@@ -250,7 +308,7 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
log_debugx("connecting to %s using ICL kernel proxy", to_addr);
error = ioctl(iscsi_fd, ISCSIDCONNECT, &idc);
if (error != 0) {
- fail(conn, strerror(errno));
+ fail(&conn->conn, strerror(errno));
log_err(1, "failed to connect to %s "
"using ICL kernel proxy: ISCSIDCONNECT", to_addr);
}
@@ -264,33 +322,33 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
#endif /* ICL_KERNEL_PROXY */
if (conn->conn_conf.isc_iser) {
- fail(conn, "iSER not supported");
+ fail(&conn->conn, "iSER not supported");
log_errx(1, "iscsid(8) compiled without ICL_KERNEL_PROXY "
"does not support iSER");
}
- conn->conn_socket = socket(to_ai->ai_family, to_ai->ai_socktype,
+ conn->conn.conn_socket = socket(to_ai->ai_family, to_ai->ai_socktype,
to_ai->ai_protocol);
- if (conn->conn_socket < 0) {
- fail(conn, strerror(errno));
+ if (conn->conn.conn_socket < 0) {
+ fail(&conn->conn, strerror(errno));
log_err(1, "failed to create socket for %s", from_addr);
}
optval = SOCKBUF_SIZE;
- if (setsockopt(conn->conn_socket, SOL_SOCKET, SO_RCVBUF,
+ if (setsockopt(conn->conn.conn_socket, SOL_SOCKET, SO_RCVBUF,
&optval, sizeof(optval)) == -1)
log_warn("setsockopt(SO_RCVBUF) failed");
optval = SOCKBUF_SIZE;
- if (setsockopt(conn->conn_socket, SOL_SOCKET, SO_SNDBUF,
+ if (setsockopt(conn->conn.conn_socket, SOL_SOCKET, SO_SNDBUF,
&optval, sizeof(optval)) == -1)
log_warn("setsockopt(SO_SNDBUF) failed");
optval = 1;
- if (setsockopt(conn->conn_socket, SOL_SOCKET, SO_NO_DDP,
+ if (setsockopt(conn->conn.conn_socket, SOL_SOCKET, SO_NO_DDP,
&optval, sizeof(optval)) == -1)
log_warn("setsockopt(SO_NO_DDP) failed");
if (conn->conn_conf.isc_dscp != -1) {
int tos = conn->conn_conf.isc_dscp << 2;
if (to_ai->ai_family == AF_INET) {
- if (setsockopt(conn->conn_socket,
+ if (setsockopt(conn->conn.conn_socket,
IPPROTO_IP, IP_TOS,
&tos, sizeof(tos)) == -1)
log_warn("setsockopt(IP_TOS) "
@@ -298,7 +356,7 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
from_addr);
} else
if (to_ai->ai_family == AF_INET6) {
- if (setsockopt(conn->conn_socket,
+ if (setsockopt(conn->conn.conn_socket,
IPPROTO_IPV6, IPV6_TCLASS,
&tos, sizeof(tos)) == -1)
log_warn("setsockopt(IPV6_TCLASS) "
@@ -309,7 +367,7 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
if (conn->conn_conf.isc_pcp != -1) {
int pcp = conn->conn_conf.isc_pcp;
if (to_ai->ai_family == AF_INET) {
- if (setsockopt(conn->conn_socket,
+ if (setsockopt(conn->conn.conn_socket,
IPPROTO_IP, IP_VLAN_PCP,
&pcp, sizeof(pcp)) == -1)
log_warn("setsockopt(IP_VLAN_PCP) "
@@ -317,7 +375,7 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
from_addr);
} else
if (to_ai->ai_family == AF_INET6) {
- if (setsockopt(conn->conn_socket,
+ if (setsockopt(conn->conn.conn_socket,
IPPROTO_IPV6, IPV6_VLAN_PCP,
&pcp, sizeof(pcp)) == -1)
log_warn("setsockopt(IPV6_VLAN_PCP) "
@@ -326,17 +384,18 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
}
}
if (from_ai != NULL) {
- error = bind(conn->conn_socket, from_ai->ai_addr,
+ error = bind(conn->conn.conn_socket, from_ai->ai_addr,
from_ai->ai_addrlen);
if (error != 0) {
- fail(conn, strerror(errno));
+ fail(&conn->conn, strerror(errno));
log_err(1, "failed to bind to %s", from_addr);
}
}
log_debugx("connecting to %s", to_addr);
- error = connect(conn->conn_socket, to_ai->ai_addr, to_ai->ai_addrlen);
+ error = connect(conn->conn.conn_socket, to_ai->ai_addr,
+ to_ai->ai_addrlen);
if (error != 0) {
- fail(conn, strerror(errno));
+ fail(&conn->conn, strerror(errno));
log_err(1, "failed to connect to %s", to_addr);
}
@@ -348,7 +407,7 @@ connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
}
static void
-handoff(struct connection *conn)
+handoff(struct iscsid_connection *conn)
{
struct iscsi_daemon_handoff idh;
int error;
@@ -357,22 +416,22 @@ handoff(struct connection *conn)
memset(&idh, 0, sizeof(idh));
idh.idh_session_id = conn->conn_session_id;
- idh.idh_socket = conn->conn_socket;
+ idh.idh_socket = conn->conn.conn_socket;
strlcpy(idh.idh_target_alias, conn->conn_target_alias,
sizeof(idh.idh_target_alias));
- idh.idh_tsih = conn->conn_tsih;
- idh.idh_statsn = conn->conn_statsn;
+ idh.idh_tsih = conn->conn.conn_tsih;
+ idh.idh_statsn = conn->conn.conn_statsn;
idh.idh_protocol_level = conn->conn_protocol_level;
- idh.idh_header_digest = conn->conn_header_digest;
- idh.idh_data_digest = conn->conn_data_digest;
+ idh.idh_header_digest = conn->conn.conn_header_digest;
+ idh.idh_data_digest = conn->conn.conn_data_digest;
idh.idh_initial_r2t = conn->conn_initial_r2t;
- idh.idh_immediate_data = conn->conn_immediate_data;
+ idh.idh_immediate_data = conn->conn.conn_immediate_data;
idh.idh_max_recv_data_segment_length =
- conn->conn_max_recv_data_segment_length;
+ conn->conn.conn_max_recv_data_segment_length;
idh.idh_max_send_data_segment_length =
- conn->conn_max_send_data_segment_length;
- idh.idh_max_burst_length = conn->conn_max_burst_length;
- idh.idh_first_burst_length = conn->conn_first_burst_length;
+ conn->conn.conn_max_send_data_segment_length;
+ idh.idh_max_burst_length = conn->conn.conn_max_burst_length;
+ idh.idh_first_burst_length = conn->conn.conn_first_burst_length;
error = ioctl(conn->conn_iscsi_fd, ISCSIDHANDOFF, &idh);
if (error != 0)
@@ -380,11 +439,13 @@ handoff(struct connection *conn)
}
void
-fail(const struct connection *conn, const char *reason)
+fail(const struct connection *base_conn, const char *reason)
{
+ const struct iscsid_connection *conn;
struct iscsi_daemon_fail idf;
int error, saved_errno;
+ conn = (const struct iscsid_connection *)base_conn;
saved_errno = errno;
memset(&idf, 0, sizeof(idf));
@@ -402,7 +463,7 @@ fail(const struct connection *conn, const char *reason)
* XXX: I CANT INTO LATIN
*/
static void
-capsicate(struct connection *conn)
+capsicate(struct iscsid_connection *conn)
{
cap_rights_t rights;
#ifdef ICL_KERNEL_PROXY
@@ -429,7 +490,7 @@ capsicate(struct connection *conn)
log_warnx("Capsicum capability mode not supported");
}
-bool
+static bool
timed_out(void)
{
@@ -519,7 +580,7 @@ register_sigchld(void)
static void
handle_request(int iscsi_fd, const struct iscsi_daemon_request *request, int timeout)
{
- struct connection *conn;
+ struct iscsid_connection *conn;
log_set_peer_addr(request->idr_conf.isc_target_addr);
if (request->idr_conf.isc_target[0] != '\0') {
diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h
index b67df4a8197f..42343c0556ae 100644
--- a/usr.sbin/iscsid/iscsid.h
+++ b/usr.sbin/iscsid/iscsid.h
@@ -37,116 +37,29 @@
#include <stdint.h>
#include <iscsi_ioctl.h>
+#include <libiscsiutil.h>
#define DEFAULT_PIDFILE "/var/run/iscsid.pid"
-#define CONN_DIGEST_NONE 0
-#define CONN_DIGEST_CRC32C 1
-
#define CONN_MUTUAL_CHALLENGE_LEN 1024
#define SOCKBUF_SIZE 1048576
-struct connection {
+struct iscsid_connection {
+ struct connection conn;
int conn_iscsi_fd;
- int conn_socket;
unsigned int conn_session_id;
struct iscsi_session_conf conn_conf;
struct iscsi_session_limits conn_limits;
char conn_target_alias[ISCSI_ADDR_LEN];
- uint8_t conn_isid[6];
- uint16_t conn_tsih;
- uint32_t conn_statsn;
int conn_protocol_level;
- int conn_header_digest;
- int conn_data_digest;
bool conn_initial_r2t;
- bool conn_immediate_data;
- int conn_max_recv_data_segment_length;
- int conn_max_send_data_segment_length;
- int conn_max_burst_length;
- int conn_first_burst_length;
struct chap *conn_mutual_chap;
};
-struct pdu {
- struct connection *pdu_connection;
- struct iscsi_bhs *pdu_bhs;
- char *pdu_data;
- size_t pdu_data_len;
-};
-
-#define KEYS_MAX 1024
-
-struct keys {
- char *keys_names[KEYS_MAX];
- char *keys_values[KEYS_MAX];
- char *keys_data;
- size_t keys_data_len;
-};
-
-#define CHAP_CHALLENGE_LEN 1024
-#define CHAP_DIGEST_LEN 16 /* Equal to MD5 digest size. */
-
-struct chap {
- unsigned char chap_id;
- char chap_challenge[CHAP_CHALLENGE_LEN];
- char chap_response[CHAP_DIGEST_LEN];
-};
-
-struct rchap {
- char *rchap_secret;
- unsigned char rchap_id;
- void *rchap_challenge;
- size_t rchap_challenge_len;
-};
-
-struct chap *chap_new(void);
-char *chap_get_id(const struct chap *chap);
-char *chap_get_challenge(const struct chap *chap);
-int chap_receive(struct chap *chap, const char *response);
-int chap_authenticate(struct chap *chap,
- const char *secret);
-void chap_delete(struct chap *chap);
-
-struct rchap *rchap_new(const char *secret);
-int rchap_receive(struct rchap *rchap,
- const char *id, const char *challenge);
-char *rchap_get_response(struct rchap *rchap);
-void rchap_delete(struct rchap *rchap);
-
-struct keys *keys_new(void);
-void keys_delete(struct keys *key);
-void keys_load(struct keys *keys, const struct pdu *pdu);
-void keys_save(struct keys *keys, struct pdu *pdu);
-const char *keys_find(struct keys *keys, const char *name);
-void keys_add(struct keys *keys,
- const char *name, const char *value);
-void keys_add_int(struct keys *keys,
- const char *name, int value);
-
-struct pdu *pdu_new(struct connection *ic);
-struct pdu *pdu_new_response(struct pdu *request);
-void pdu_receive(struct pdu *request);
-void pdu_send(struct pdu *response);
-void pdu_delete(struct pdu *ip);
-
-void login(struct connection *ic);
-
-void discovery(struct connection *ic);
+void login(struct iscsid_connection *ic);
-void log_init(int level);
-void log_set_peer_name(const char *name);
-void log_set_peer_addr(const char *addr);
-void log_err(int, const char *, ...)
- __dead2 __printflike(2, 3);
-void log_errx(int, const char *, ...)
- __dead2 __printflike(2, 3);
-void log_warn(const char *, ...) __printflike(1, 2);
-void log_warnx(const char *, ...) __printflike(1, 2);
-void log_debugx(const char *, ...) __printflike(1, 2);
+void discovery(struct iscsid_connection *ic);
-char *checked_strdup(const char *);
-bool timed_out(void);
void fail(const struct connection *, const char *);
#endif /* !ISCSID_H */
diff --git a/usr.sbin/iscsid/keys.c b/usr.sbin/iscsid/keys.c
deleted file mode 100644
index e1d49ff585de..000000000000
--- a/usr.sbin/iscsid/keys.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "iscsid.h"
-
-struct keys *
-keys_new(void)
-{
- struct keys *keys;
-
- keys = calloc(1, sizeof(*keys));
- if (keys == NULL)
- log_err(1, "calloc");
-
- return (keys);
-}
-
-void
-keys_delete(struct keys *keys)
-{
-
- free(keys->keys_data);
- free(keys);
-}
-
-void
-keys_load(struct keys *keys, const struct pdu *pdu)
-{
- int i;
- char *pair;
- size_t pair_len;
-
- if (pdu->pdu_data_len == 0)
- return;
-
- if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
- log_errx(1, "protocol error: key not NULL-terminated\n");
-
- assert(keys->keys_data == NULL);
- keys->keys_data_len = pdu->pdu_data_len;
- keys->keys_data = malloc(keys->keys_data_len);
- if (keys->keys_data == NULL)
- log_err(1, "malloc");
- memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len);
-
- /*
- * XXX: Review this carefully.
- */
- pair = keys->keys_data;
- for (i = 0;; i++) {
- if (i >= KEYS_MAX)
- log_errx(1, "too many keys received");
-
- pair_len = strlen(pair);
-
- keys->keys_values[i] = pair;
- keys->keys_names[i] = strsep(&keys->keys_values[i], "=");
- if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL)
- log_errx(1, "malformed keys");
- log_debugx("key received: \"%s=%s\"",
- keys->keys_names[i], keys->keys_values[i]);
-
- pair += pair_len + 1; /* +1 to skip the terminating '\0'. */
- if (pair == keys->keys_data + keys->keys_data_len)
- break;
- assert(pair < keys->keys_data + keys->keys_data_len);
- }
-}
-
-void
-keys_save(struct keys *keys, struct pdu *pdu)
-{
- char *data;
- size_t len;
- int i;
-
- /*
- * XXX: Not particularly efficient.
- */
- len = 0;
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- break;
- /*
- * +1 for '=', +1 for '\0'.
- */
- len += strlen(keys->keys_names[i]) +
- strlen(keys->keys_values[i]) + 2;
- }
-
- if (len == 0)
- return;
-
- data = malloc(len);
- if (data == NULL)
- log_err(1, "malloc");
-
- pdu->pdu_data = data;
- pdu->pdu_data_len = len;
-
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- break;
- data += sprintf(data, "%s=%s",
- keys->keys_names[i], keys->keys_values[i]);
- data += 1; /* for '\0'. */
- }
-}
-
-const char *
-keys_find(struct keys *keys, const char *name)
-{
- int i;
-
- /*
- * Note that we don't handle duplicated key names here,
- * as they are not supposed to happen in requests, and if they do,
- * it's an initiator error.
- */
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL)
- return (NULL);
- if (strcmp(keys->keys_names[i], name) == 0)
- return (keys->keys_values[i]);
- }
- return (NULL);
-}
-
-void
-keys_add(struct keys *keys, const char *name, const char *value)
-{
- int i;
-
- log_debugx("key to send: \"%s=%s\"", name, value);
-
- /*
- * Note that we don't check for duplicates here, as they are perfectly
- * fine in responses, e.g. the "TargetName" keys in discovery sesion
- * response.
- */
- for (i = 0; i < KEYS_MAX; i++) {
- if (keys->keys_names[i] == NULL) {
- keys->keys_names[i] = checked_strdup(name);
- keys->keys_values[i] = checked_strdup(value);
- return;
- }
- }
- log_errx(1, "too many keys");
-}
-
-void
-keys_add_int(struct keys *keys, const char *name, int value)
-{
- char *str;
- int ret;
-
- ret = asprintf(&str, "%d", value);
- if (ret <= 0)
- log_err(1, "asprintf");
-
- keys_add(keys, name, str);
- free(str);
-}
diff --git a/usr.sbin/iscsid/log.c b/usr.sbin/iscsid/log.c
deleted file mode 100644
index fe0009be774d..000000000000
--- a/usr.sbin/iscsid/log.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <vis.h>
-
-#include "iscsid.h"
-
-static int log_level = 0;
-static char *peer_name = NULL;
-static char *peer_addr = NULL;
-
-#define MSGBUF_LEN 1024
-
-void
-log_init(int level)
-{
-
- log_level = level;
- openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
-}
-
-void
-log_set_peer_name(const char *name)
-{
-
- /*
- * XXX: Turn it into assertion?
- */
- if (peer_name != NULL)
- log_errx(1, "%s called twice", __func__);
- if (peer_addr == NULL)
- log_errx(1, "%s called before log_set_peer_addr", __func__);
-
- peer_name = checked_strdup(name);
-}
-
-void
-log_set_peer_addr(const char *addr)
-{
-
- /*
- * XXX: Turn it into assertion?
- */
- if (peer_addr != NULL)
- log_errx(1, "%s called twice", __func__);
-
- peer_addr = checked_strdup(addr);
-}
-
-static void
-log_common(int priority, int log_errno, const char *fmt, va_list ap)
-{
- static char msgbuf[MSGBUF_LEN];
- static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
- char *errstr;
- int ret;
-
- ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
- if (ret < 0) {
- fprintf(stderr, "%s: snprintf failed", getprogname());
- syslog(LOG_CRIT, "snprintf failed");
- exit(1);
- }
-
- ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL);
- if (ret < 0) {
- fprintf(stderr, "%s: strnvis failed", getprogname());
- syslog(LOG_CRIT, "strnvis failed");
- exit(1);
- }
-
- if (log_errno == -1) {
- if (peer_name != NULL) {
- fprintf(stderr, "%s: %s (%s): %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised);
- syslog(priority, "%s (%s): %s",
- peer_addr, peer_name, msgbuf_strvised);
- } else if (peer_addr != NULL) {
- fprintf(stderr, "%s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised);
- syslog(priority, "%s: %s",
- peer_addr, msgbuf_strvised);
- } else {
- fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised);
- syslog(priority, "%s", msgbuf_strvised);
- }
-
- } else {
- errstr = strerror(log_errno);
-
- if (peer_name != NULL) {
- fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised, errstr);
- syslog(priority, "%s (%s): %s: %s",
- peer_addr, peer_name, msgbuf_strvised, errstr);
- } else if (peer_addr != NULL) {
- fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised, errstr);
- syslog(priority, "%s: %s: %s",
- peer_addr, msgbuf_strvised, errstr);
- } else {
- fprintf(stderr, "%s: %s: %s\n", getprogname(),
- msgbuf_strvised, errstr);
- syslog(priority, "%s: %s",
- msgbuf_strvised, errstr);
- }
- }
-}
-
-void
-log_err(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_CRIT, errno, fmt, ap);
- va_end(ap);
-
- exit(eval);
-}
-
-void
-log_errx(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_CRIT, -1, fmt, ap);
- va_end(ap);
-
- exit(eval);
-}
-
-void
-log_warn(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_WARNING, errno, fmt, ap);
- va_end(ap);
-}
-
-void
-log_warnx(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- log_common(LOG_WARNING, -1, fmt, ap);
- va_end(ap);
-}
-
-void
-log_debugx(const char *fmt, ...)
-{
- va_list ap;
-
- if (log_level == 0)
- return;
-
- va_start(ap, fmt);
- log_common(LOG_DEBUG, -1, fmt, ap);
- va_end(ap);
-}
diff --git a/usr.sbin/iscsid/login.c b/usr.sbin/iscsid/login.c
index 3f0020ef140b..11a22dfcfaf1 100644
--- a/usr.sbin/iscsid/login.c
+++ b/usr.sbin/iscsid/login.c
@@ -160,7 +160,7 @@ login_target_error_str(int class, int detail)
}
static void
-kernel_modify(const struct connection *conn, const char *target_address)
+kernel_modify(const struct iscsid_connection *conn, const char *target_address)
{
struct iscsi_session_modify ism;
int error;
@@ -188,7 +188,7 @@ kernel_modify(const struct connection *conn, const char *target_address)
* as described in draft.
*/
static void
-login_handle_redirection(struct connection *conn, struct pdu *response)
+login_handle_redirection(struct iscsid_connection *conn, struct pdu *response)
{
struct iscsi_bhs_login_response *bhslr;
struct keys *response_keys;
@@ -241,7 +241,8 @@ login_receive(struct connection *conn)
log_errx(1, "received Login PDU with unsupported "
"Version-active 0x%x", bhslr->bhslr_version_active);
if (bhslr->bhslr_status_class == 1) {
- login_handle_redirection(conn, response);
+ login_handle_redirection((struct iscsid_connection *)conn,
+ response);
log_debugx("redirection handled; exiting");
exit(0);
}
@@ -328,7 +329,7 @@ login_list_prefers(const char *list,
}
static void
-login_negotiate_key(struct connection *conn, const char *name,
+login_negotiate_key(struct iscsid_connection *conn, const char *name,
const char *value)
{
struct iscsi_session_limits *isl;
@@ -351,7 +352,7 @@ login_negotiate_key(struct connection *conn, const char *name,
case 1:
log_debugx("target prefers CRC32C "
"for header digest; we'll use it");
- conn->conn_header_digest = CONN_DIGEST_CRC32C;
+ conn->conn.conn_header_digest = CONN_DIGEST_CRC32C;
break;
case 2:
log_debugx("target prefers not to do "
@@ -368,7 +369,7 @@ login_negotiate_key(struct connection *conn, const char *name,
case 1:
log_debugx("target prefers CRC32C "
"for data digest; we'll use it");
- conn->conn_data_digest = CONN_DIGEST_CRC32C;
+ conn->conn.conn_data_digest = CONN_DIGEST_CRC32C;
break;
case 2:
log_debugx("target prefers not to do "
@@ -388,9 +389,9 @@ login_negotiate_key(struct connection *conn, const char *name,
conn->conn_initial_r2t = false;
} else if (strcmp(name, "ImmediateData") == 0) {
if (strcmp(value, "Yes") == 0)
- conn->conn_immediate_data = true;
+ conn->conn.conn_immediate_data = true;
else
- conn->conn_immediate_data = false;
+ conn->conn.conn_immediate_data = false;
} else if (strcmp(name, "MaxRecvDataSegmentLength") == 0) {
tmp = strtoul(value, NULL, 10);
if (tmp <= 0)
@@ -402,7 +403,7 @@ login_negotiate_key(struct connection *conn, const char *name,
isl->isl_max_send_data_segment_length);
tmp = isl->isl_max_send_data_segment_length;
}
- conn->conn_max_send_data_segment_length = tmp;
+ conn->conn.conn_max_send_data_segment_length = tmp;
} else if (strcmp(name, "MaxBurstLength") == 0) {
tmp = strtoul(value, NULL, 10);
if (tmp <= 0)
@@ -412,7 +413,7 @@ login_negotiate_key(struct connection *conn, const char *name,
"from %d to %d", tmp, isl->isl_max_burst_length);
tmp = isl->isl_max_burst_length;
}
- conn->conn_max_burst_length = tmp;
+ conn->conn.conn_max_burst_length = tmp;
} else if (strcmp(name, "FirstBurstLength") == 0) {
tmp = strtoul(value, NULL, 10);
if (tmp <= 0)
@@ -422,7 +423,7 @@ login_negotiate_key(struct connection *conn, const char *name,
"from %d to %d", tmp, isl->isl_first_burst_length);
tmp = isl->isl_first_burst_length;
}
- conn->conn_first_burst_length = tmp;
+ conn->conn.conn_first_burst_length = tmp;
} else if (strcmp(name, "DefaultTime2Wait") == 0) {
/* Ignore */
} else if (strcmp(name, "DefaultTime2Retain") == 0) {
@@ -455,7 +456,7 @@ login_negotiate_key(struct connection *conn, const char *name,
isl->isl_max_recv_data_segment_length);
tmp = isl->isl_max_recv_data_segment_length;
}
- conn->conn_max_recv_data_segment_length = tmp;
+ conn->conn.conn_max_recv_data_segment_length = tmp;
} else if (strcmp(name, "TargetPortalGroupTag") == 0) {
/* Ignore */
} else if (strcmp(name, "TargetRecvDataSegmentLength") == 0) {
@@ -470,14 +471,14 @@ login_negotiate_key(struct connection *conn, const char *name,
isl->isl_max_send_data_segment_length);
tmp = isl->isl_max_send_data_segment_length;
}
- conn->conn_max_send_data_segment_length = tmp;
+ conn->conn.conn_max_send_data_segment_length = tmp;
} else {
log_debugx("unknown key \"%s\"; ignoring", name);
}
}
static void
-login_negotiate(struct connection *conn)
+login_negotiate(struct iscsid_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
@@ -486,7 +487,8 @@ login_negotiate(struct connection *conn)
struct iscsi_session_limits *isl;
log_debugx("beginning operational parameter negotiation");
- request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
+ request = login_new_request(&conn->conn,
+ BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
request_keys = keys_new();
isl = &conn->conn_limits;
@@ -535,7 +537,7 @@ login_negotiate(struct connection *conn)
isl->isl_max_recv_data_segment_length);
}
- conn->conn_max_recv_data_segment_length =
+ conn->conn.conn_max_recv_data_segment_length =
isl->isl_max_recv_data_segment_length;
keys_add(request_keys, "DefaultTime2Wait", "0");
@@ -548,7 +550,7 @@ login_negotiate(struct connection *conn)
pdu_delete(request);
request = NULL;
- response = login_receive(conn);
+ response = login_receive(&conn->conn);
response_keys = keys_new();
keys_load(response_keys, response);
for (i = 0; i < KEYS_MAX; i++) {
@@ -579,12 +581,12 @@ login_negotiate(struct connection *conn)
pdu_delete(response);
- request = login_new_request(conn,
+ request = login_new_request(&conn->conn,
BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
pdu_send(request);
pdu_delete(request);
- response = login_receive(conn);
+ response = login_receive(&conn->conn);
}
if (login_nsg(response) != BHSLR_STAGE_FULL_FEATURE_PHASE)
@@ -614,7 +616,7 @@ login_send_chap_a(struct connection *conn)
static void
login_send_chap_r(struct pdu *response)
{
- struct connection *conn;
+ struct iscsid_connection *conn;
struct pdu *request;
struct keys *request_keys, *response_keys;
struct rchap *rchap;
@@ -631,7 +633,7 @@ login_send_chap_r(struct pdu *response)
* CHAP challenge; our CHAP response goes into 'request'.
*/
- conn = response->pdu_connection;
+ conn = (struct iscsid_connection *)response->pdu_connection;
response_keys = keys_new();
keys_load(response_keys, response);
@@ -665,7 +667,8 @@ login_send_chap_r(struct pdu *response)
keys_delete(response_keys);
- request = login_new_request(conn, BHSLR_STAGE_SECURITY_NEGOTIATION);
+ request = login_new_request(&conn->conn,
+ BHSLR_STAGE_SECURITY_NEGOTIATION);
request_keys = keys_new();
keys_add(request_keys, "CHAP_N", conn->conn_conf.isc_user);
keys_add(request_keys, "CHAP_R", chap_r);
@@ -699,12 +702,12 @@ login_send_chap_r(struct pdu *response)
static void
login_verify_mutual(const struct pdu *response)
{
- struct connection *conn;
+ struct iscsid_connection *conn;
struct keys *response_keys;
const char *chap_n, *chap_r;
int error;
- conn = response->pdu_connection;
+ conn = (struct iscsid_connection *)response->pdu_connection;
response_keys = keys_new();
keys_load(response_keys, response);
@@ -721,14 +724,14 @@ login_verify_mutual(const struct pdu *response)
log_errx(1, "received CHAP Response PDU with invalid CHAP_R");
if (strcmp(chap_n, conn->conn_conf.isc_mutual_user) != 0) {
- fail(conn, "Mutual CHAP failed");
+ fail(&conn->conn, "Mutual CHAP failed");
log_errx(1, "mutual CHAP authentication failed: wrong user");
}
error = chap_authenticate(conn->conn_mutual_chap,
conn->conn_conf.isc_mutual_secret);
if (error != 0) {
- fail(conn, "Mutual CHAP failed");
+ fail(&conn->conn, "Mutual CHAP failed");
log_errx(1, "mutual CHAP authentication failed: wrong secret");
}
@@ -740,15 +743,15 @@ login_verify_mutual(const struct pdu *response)
}
static void
-login_chap(struct connection *conn)
+login_chap(struct iscsid_connection *conn)
{
struct pdu *response;
log_debugx("beginning CHAP authentication; sending CHAP_A");
- login_send_chap_a(conn);
+ login_send_chap_a(&conn->conn);
log_debugx("waiting for CHAP_A/CHAP_C/CHAP_I");
- response = login_receive(conn);
+ response = login_receive(&conn->conn);
log_debugx("sending CHAP_N/CHAP_R");
login_send_chap_r(response);
@@ -759,7 +762,7 @@ login_chap(struct connection *conn)
*/
log_debugx("waiting for CHAP result");
- response = login_receive(conn);
+ response = login_receive(&conn->conn);
if (conn->conn_conf.isc_mutual_user[0] != '\0')
login_verify_mutual(response);
pdu_delete(response);
@@ -768,7 +771,7 @@ login_chap(struct connection *conn)
}
void
-login(struct connection *conn)
+login(struct iscsid_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
@@ -777,7 +780,8 @@ login(struct connection *conn)
int i;
log_debugx("beginning Login phase; sending Login PDU");
- request = login_new_request(conn, BHSLR_STAGE_SECURITY_NEGOTIATION);
+ request = login_new_request(&conn->conn,
+ BHSLR_STAGE_SECURITY_NEGOTIATION);
request_keys = keys_new();
if (conn->conn_conf.isc_mutual_user[0] != '\0') {
keys_add(request_keys, "AuthMethod", "CHAP");
@@ -817,7 +821,7 @@ login(struct connection *conn)
pdu_send(request);
pdu_delete(request);
- response = login_receive(conn);
+ response = login_receive(&conn->conn);
response_keys = keys_new();
keys_load(response_keys, response);
@@ -875,14 +879,14 @@ login(struct connection *conn)
}
if (strcmp(auth_method, "CHAP") != 0) {
- fail(conn, "Unsupported AuthMethod");
+ fail(&conn->conn, "Unsupported AuthMethod");
log_errx(1, "received response "
"with unsupported AuthMethod \"%s\"", auth_method);
}
if (conn->conn_conf.isc_user[0] == '\0' ||
conn->conn_conf.isc_secret[0] == '\0') {
- fail(conn, "Authentication required");
+ fail(&conn->conn, "Authentication required");
log_errx(1, "target requests CHAP authentication, but we don't "
"have user and secret");
}
diff --git a/usr.sbin/iscsid/pdu.c b/usr.sbin/iscsid/pdu.c
deleted file mode 100644
index 246195bf1dcc..000000000000
--- a/usr.sbin/iscsid/pdu.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- *
- * This software was 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "iscsid.h"
-#include "iscsi_proto.h"
-
-#ifdef ICL_KERNEL_PROXY
-#include <sys/ioctl.h>
-#endif
-
-static int
-pdu_ahs_length(const struct pdu *pdu)
-{
-
- return (pdu->pdu_bhs->bhs_total_ahs_len * 4);
-}
-
-static int
-pdu_data_segment_length(const struct pdu *pdu)
-{
- uint32_t len = 0;
-
- len += pdu->pdu_bhs->bhs_data_segment_len[0];
- len <<= 8;
- len += pdu->pdu_bhs->bhs_data_segment_len[1];
- len <<= 8;
- len += pdu->pdu_bhs->bhs_data_segment_len[2];
-
- return (len);
-}
-
-static void
-pdu_set_data_segment_length(struct pdu *pdu, uint32_t len)
-{
-
- pdu->pdu_bhs->bhs_data_segment_len[2] = len;
- pdu->pdu_bhs->bhs_data_segment_len[1] = len >> 8;
- pdu->pdu_bhs->bhs_data_segment_len[0] = len >> 16;
-}
-
-struct pdu *
-pdu_new(struct connection *conn)
-{
- struct pdu *pdu;
-
- pdu = calloc(1, sizeof(*pdu));
- if (pdu == NULL)
- log_err(1, "calloc");
-
- pdu->pdu_bhs = calloc(1, sizeof(*pdu->pdu_bhs));
- if (pdu->pdu_bhs == NULL)
- log_err(1, "calloc");
-
- pdu->pdu_connection = conn;
-
- return (pdu);
-}
-
-struct pdu *
-pdu_new_response(struct pdu *request)
-{
-
- return (pdu_new(request->pdu_connection));
-}
-
-#ifdef ICL_KERNEL_PROXY
-
-static void
-pdu_receive_proxy(struct pdu *pdu)
-{
- struct connection *conn;
- struct iscsi_daemon_receive *idr;
- size_t len;
- int error;
-
- conn = pdu->pdu_connection;
- assert(conn->conn_conf.isc_iser != 0);
-
- pdu->pdu_data = malloc(conn->conn_max_recv_data_segment_length);
- if (pdu->pdu_data == NULL)
- log_err(1, "malloc");
-
- idr = calloc(1, sizeof(*idr));
- if (idr == NULL)
- log_err(1, "calloc");
-
- idr->idr_session_id = conn->conn_session_id;
- idr->idr_bhs = pdu->pdu_bhs;
- idr->idr_data_segment_len = conn->conn_max_recv_data_segment_length;
- idr->idr_data_segment = pdu->pdu_data;
-
- error = ioctl(conn->conn_iscsi_fd, ISCSIDRECEIVE, idr);
- if (error != 0)
- log_err(1, "ISCSIDRECEIVE");
-
- 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;
-
- free(idr);
-}
-
-static void
-pdu_send_proxy(struct pdu *pdu)
-{
- struct connection *conn;
- struct iscsi_daemon_send *ids;
- int error;
-
- conn = pdu->pdu_connection;
- assert(conn->conn_conf.isc_iser != 0);
-
- pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
-
- ids = calloc(1, sizeof(*ids));
- if (ids == NULL)
- log_err(1, "calloc");
-
- ids->ids_session_id = conn->conn_session_id;
- ids->ids_bhs = pdu->pdu_bhs;
- ids->ids_data_segment_len = pdu->pdu_data_len;
- ids->ids_data_segment = pdu->pdu_data;
-
- error = ioctl(conn->conn_iscsi_fd, ISCSIDSEND, ids);
- if (error != 0)
- log_err(1, "ISCSIDSEND");
-
- free(ids);
-}
-
-#endif /* ICL_KERNEL_PROXY */
-
-static size_t
-pdu_padding(const struct pdu *pdu)
-{
-
- if ((pdu->pdu_data_len % 4) != 0)
- return (4 - (pdu->pdu_data_len % 4));
-
- return (0);
-}
-
-static void
-pdu_read(const struct connection *conn, char *data, size_t len)
-{
- ssize_t ret;
-
- while (len > 0) {
- ret = read(conn->conn_socket, data, len);
- if (ret < 0) {
- if (timed_out()) {
- fail(conn, "Login Phase timeout");
- log_errx(1, "exiting due to timeout");
- }
- fail(conn, strerror(errno));
- log_err(1, "read");
- } else if (ret == 0) {
- fail(conn, "connection lost");
- log_errx(1, "read: connection lost");
- }
- len -= ret;
- data += ret;
- }
-}
-
-void
-pdu_receive(struct pdu *pdu)
-{
- struct connection *conn;
- size_t len, padding;
- char dummy[4];
-
- conn = pdu->pdu_connection;
-#ifdef ICL_KERNEL_PROXY
- if (conn->conn_conf.isc_iser != 0)
- return (pdu_receive_proxy(pdu));
-#endif
- assert(conn->conn_conf.isc_iser == 0);
-
- pdu_read(conn, (char *)pdu->pdu_bhs, sizeof(*pdu->pdu_bhs));
-
- len = pdu_ahs_length(pdu);
- if (len > 0)
- log_errx(1, "protocol error: non-empty AHS");
-
- len = pdu_data_segment_length(pdu);
- if (len > 0) {
- if (len > (size_t)conn->conn_max_recv_data_segment_length) {
- log_errx(1, "protocol error: received PDU "
- "with DataSegmentLength exceeding %d",
- conn->conn_max_recv_data_segment_length);
- }
-
- pdu->pdu_data_len = len;
- pdu->pdu_data = malloc(len);
- if (pdu->pdu_data == NULL)
- log_err(1, "malloc");
-
- pdu_read(conn, (char *)pdu->pdu_data, pdu->pdu_data_len);
-
- padding = pdu_padding(pdu);
- if (padding != 0) {
- assert(padding < sizeof(dummy));
- pdu_read(conn, (char *)dummy, padding);
- }
- }
-}
-
-void
-pdu_send(struct pdu *pdu)
-{
- struct connection *conn;
- ssize_t ret, total_len;
- size_t padding;
- uint32_t zero = 0;
- struct iovec iov[3];
- int iovcnt;
-
- conn = pdu->pdu_connection;
-#ifdef ICL_KERNEL_PROXY
- if (conn->conn_conf.isc_iser != 0)
- return (pdu_send_proxy(pdu));
-#endif
-
- assert(conn->conn_conf.isc_iser == 0);
-
- pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
- iov[0].iov_base = pdu->pdu_bhs;
- iov[0].iov_len = sizeof(*pdu->pdu_bhs);
- total_len = iov[0].iov_len;
- iovcnt = 1;
-
- if (pdu->pdu_data_len > 0) {
- iov[1].iov_base = pdu->pdu_data;
- iov[1].iov_len = pdu->pdu_data_len;
- total_len += iov[1].iov_len;
- iovcnt = 2;
-
- padding = pdu_padding(pdu);
- if (padding > 0) {
- assert(padding < sizeof(zero));
- iov[2].iov_base = &zero;
- iov[2].iov_len = padding;
- total_len += iov[2].iov_len;
- iovcnt = 3;
- }
- }
-
- ret = writev(conn->conn_socket, iov, iovcnt);
- if (ret < 0) {
- if (timed_out())
- log_errx(1, "exiting due to timeout");
- log_err(1, "writev");
- }
- if (ret != total_len)
- log_errx(1, "short write");
-}
-
-void
-pdu_delete(struct pdu *pdu)
-{
-
- free(pdu->pdu_data);
- free(pdu->pdu_bhs);
- free(pdu);
-}