Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115918068
D33544.id100436.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
85 KB
Referenced Files
None
Subscribers
None
D33544.id100436.diff
View Options
Index: lib/Makefile
===================================================================
--- lib/Makefile
+++ lib/Makefile
@@ -63,6 +63,7 @@
libgeom \
libifconfig \
libipsec \
+ libiscsiutil \
libjail \
libkiconv \
libkvm \
Index: lib/libiscsiutil/Makefile
===================================================================
--- /dev/null
+++ lib/libiscsiutil/Makefile
@@ -0,0 +1,10 @@
+LIB= iscsiutil
+INTERNALLIB=
+PACKAGE= iscsi
+
+INCS= libiscsiutil.h
+
+SRCS= chap.c connection.c keys.c log.c pdu.c utils.c
+CFLAGS+= -I${SRCTOP}/sys/dev/iscsi
+
+.include <bsd.lib.mk>
Index: lib/libiscsiutil/chap.c
===================================================================
--- lib/libiscsiutil/chap.c
+++ lib/libiscsiutil/chap.c
@@ -26,12 +26,8 @@
* 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>
@@ -39,7 +35,7 @@
#include <resolv.h>
#include <md5.h>
-#include "ctld.h"
+#include "libiscsiutil.h"
static void
chap_compute_md5(const char id, const char *secret,
Index: lib/libiscsiutil/connection.c
===================================================================
--- /dev/null
+++ lib/libiscsiutil/connection.c
@@ -0,0 +1,53 @@
+/*-
+ * 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 <string.h>
+
+#include "libiscsiutil.h"
+
+void
+connection_init(struct connection *conn, const struct connection_ops *ops,
+ bool use_proxy)
+{
+ memset(conn, 0, sizeof(*conn));
+ conn->conn_ops = ops;
+ conn->conn_use_proxy = use_proxy;
+
+ /*
+ * Default values, from RFC 3720, section 12.
+ */
+ conn->conn_header_digest = CONN_DIGEST_NONE;
+ conn->conn_data_digest = CONN_DIGEST_NONE;
+ 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;
+}
Index: lib/libiscsiutil/keys.c
===================================================================
--- lib/libiscsiutil/keys.c
+++ lib/libiscsiutil/keys.c
@@ -26,18 +26,14 @@
* 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"
+#include "libiscsiutil.h"
struct keys *
keys_new(void)
Index: lib/libiscsiutil/libiscsiutil.h
===================================================================
--- lib/libiscsiutil/libiscsiutil.h
+++ lib/libiscsiutil/libiscsiutil.h
@@ -26,62 +26,57 @@
* 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.
- *
- * $FreeBSD$
*/
-#ifndef ISCSID_H
-#define ISCSID_H
+#ifndef __LIBISCSIUTIL_H__
+#define __LIBISCSIUTIL_H__
+#include <sys/types.h>
#include <stdbool.h>
-#include <stdint.h>
-#include <iscsi_ioctl.h>
-
-#define DEFAULT_PIDFILE "/var/run/iscsid.pid"
+struct connection_ops;
#define CONN_DIGEST_NONE 0
#define CONN_DIGEST_CRC32C 1
-#define CONN_MUTUAL_CHALLENGE_LEN 1024
-#define SOCKBUF_SIZE 1048576
-
struct connection {
- 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;
+ const struct connection_ops *conn_ops;
+ int conn_socket;
+ uint8_t conn_isid[6];
+ uint16_t conn_tsih;
+ uint32_t conn_cmdsn;
+ uint32_t conn_statsn;
+ int conn_header_digest;
+ int conn_data_digest;
+ bool conn_immediate_data;
+ bool conn_use_proxy;
+ 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 pdu {
- struct connection *pdu_connection;
- struct iscsi_bhs *pdu_bhs;
- char *pdu_data;
- size_t pdu_data_len;
+ struct connection *pdu_connection;
+ struct iscsi_bhs *pdu_bhs;
+ char *pdu_data;
+ size_t pdu_data_len;
+};
+
+struct connection_ops {
+ bool (*timed_out)(void);
+ void (*pdu_receive_proxy)(struct pdu *);
+ void (*pdu_send_proxy)(struct pdu *);
+ void (*fail)(const struct connection *, const char *);
};
#define KEYS_MAX 1024
struct keys {
- char *keys_names[KEYS_MAX];
- char *keys_values[KEYS_MAX];
- char *keys_data;
- size_t keys_data_len;
+ char *keys_names[KEYS_MAX];
+ char *keys_values[KEYS_MAX];
+ char *keys_data;
+ size_t keys_data_len;
};
#define CHAP_CHALLENGE_LEN 1024
@@ -126,13 +121,16 @@
struct pdu *pdu_new(struct connection *ic);
struct pdu *pdu_new_response(struct pdu *request);
+int pdu_ahs_length(const struct pdu *pdu);
+int pdu_data_segment_length(const struct pdu *pdu);
+void pdu_set_data_segment_length(struct pdu *pdu,
+ uint32_t len);
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 connection_init(struct connection *conn,
+ const struct connection_ops *ops, bool use_proxy);
void log_init(int level);
void log_set_peer_name(const char *name);
@@ -146,7 +144,5 @@
void log_debugx(const char *, ...) __printflike(1, 2);
char *checked_strdup(const char *);
-bool timed_out(void);
-void fail(const struct connection *, const char *);
-#endif /* !ISCSID_H */
+#endif /* !__LIBISCSIUTIL_H__ */
Index: lib/libiscsiutil/log.c
===================================================================
--- lib/libiscsiutil/log.c
+++ lib/libiscsiutil/log.c
@@ -26,12 +26,8 @@
* 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>
@@ -40,7 +36,7 @@
#include <syslog.h>
#include <vis.h>
-#include "ctld.h"
+#include "libiscsiutil.h"
static int log_level = 0;
static char *peer_name = NULL;
Index: lib/libiscsiutil/pdu.c
===================================================================
--- lib/libiscsiutil/pdu.c
+++ lib/libiscsiutil/pdu.c
@@ -35,26 +35,22 @@
#include <sys/types.h>
#include <sys/uio.h>
#include <assert.h>
+#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include "ctld.h"
-#include "iscsi_proto.h"
+#include <iscsi_proto.h>
+#include "libiscsiutil.h"
-#ifdef ICL_KERNEL_PROXY
-#include <sys/ioctl.h>
-#endif
-
-extern bool proxy_mode;
-
-static int
+int
pdu_ahs_length(const struct pdu *pdu)
{
return (pdu->pdu_bhs->bhs_total_ahs_len * 4);
}
-static int
+int
pdu_data_segment_length(const struct pdu *pdu)
{
uint32_t len = 0;
@@ -68,7 +64,7 @@
return (len);
}
-static void
+void
pdu_set_data_segment_length(struct pdu *pdu, uint32_t len)
{
@@ -102,40 +98,6 @@
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)
{
@@ -147,18 +109,24 @@
}
static void
-pdu_read(int fd, char *data, size_t len)
+pdu_read(const struct connection *conn, char *data, size_t len)
{
ssize_t ret;
while (len > 0) {
- ret = read(fd, data, len);
+ ret = read(conn->conn_socket, data, len);
if (ret < 0) {
- if (timed_out())
+ if (conn->conn_ops->timed_out()) {
+ conn->conn_ops->fail(conn,
+ "Login Phase timeout");
log_errx(1, "exiting due to timeout");
+ }
+ conn->conn_ops->fail(conn, strerror(errno));
log_err(1, "read");
- } else if (ret == 0)
+ } else if (ret == 0) {
+ conn->conn_ops->fail(conn, "connection lost");
log_errx(1, "read: connection lost");
+ }
len -= ret;
data += ret;
}
@@ -171,16 +139,11 @@
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;
+ if (conn->conn_use_proxy)
+ return (conn->conn_ops->pdu_receive_proxy(pdu));
- pdu_read(conn->conn_socket, (char *)pdu->pdu_bhs,
- sizeof(*pdu->pdu_bhs));
+ pdu_read(conn, (char *)pdu->pdu_bhs, sizeof(*pdu->pdu_bhs));
len = pdu_ahs_length(pdu);
if (len > 0)
@@ -199,13 +162,12 @@
if (pdu->pdu_data == NULL)
log_err(1, "malloc");
- pdu_read(conn->conn_socket, (char *)pdu->pdu_data,
- pdu->pdu_data_len);
+ 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->conn_socket, (char *)dummy, padding);
+ pdu_read(conn, (char *)dummy, padding);
}
}
}
@@ -213,18 +175,16 @@
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;
-#ifdef ICL_KERNEL_PROXY
- if (proxy_mode)
- return (pdu_send_proxy(pdu));
-#endif
-
- assert(proxy_mode == false);
+ conn = pdu->pdu_connection;
+ if (conn->conn_use_proxy)
+ return (conn->conn_ops->pdu_send_proxy(pdu));
pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
iov[0].iov_base = pdu->pdu_bhs;
@@ -248,9 +208,9 @@
}
}
- ret = writev(pdu->pdu_connection->conn_socket, iov, iovcnt);
+ ret = writev(conn->conn_socket, iov, iovcnt);
if (ret < 0) {
- if (timed_out())
+ if (conn->conn_ops->timed_out())
log_errx(1, "exiting due to timeout");
log_err(1, "writev");
}
Index: lib/libiscsiutil/utils.c
===================================================================
--- /dev/null
+++ lib/libiscsiutil/utils.c
@@ -0,0 +1,44 @@
+/*-
+ * 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 <string.h>
+
+#include "libiscsiutil.h"
+
+char *
+checked_strdup(const char *s)
+{
+ char *c;
+
+ c = strdup(s);
+ if (c == NULL)
+ log_err(1, "strdup");
+ return (c);
+}
Index: rescue/rescue/Makefile
===================================================================
--- rescue/rescue/Makefile
+++ rescue/rescue/Makefile
@@ -236,6 +236,9 @@
.if ${MK_ISCSI} != "no"
CRUNCH_PROGS_usr.bin+= iscsictl
CRUNCH_PROGS_usr.sbin+= iscsid
+
+CRUNCH_LIBS+= ${OBJTOP}/lib/libiscsiutil/libiscsiutil.a
+CRUNCH_BUILDOPTS+= CRUNCH_CFLAGS+=-I${OBJTOP}/lib/libiscsiutil
.endif
.include <bsd.crunchgen.mk>
Index: share/mk/bsd.libnames.mk
===================================================================
--- share/mk/bsd.libnames.mk
+++ share/mk/bsd.libnames.mk
@@ -83,6 +83,7 @@
LIBICP?= ${LIBDESTDIR}${LIBDIR_BASE}/libicp.a
LIBIPSEC?= ${LIBDESTDIR}${LIBDIR_BASE}/libipsec.a
LIBIPT?= ${LIBDESTDIR}${LIBDIR_BASE}/libipt.a
+LIBISCSIUTIL?= ${LIBDESTDIR}${LIBDIR_BASE}/libiscsiutil.a
LIBJAIL?= ${LIBDESTDIR}${LIBDIR_BASE}/libjail.a
LIBKADM5CLNT?= ${LIBDESTDIR}${LIBDIR_BASE}/libkadm5clnt.a
LIBKADM5SRV?= ${LIBDESTDIR}${LIBDIR_BASE}/libkadm5srv.a
Index: share/mk/src.libnames.mk
===================================================================
--- share/mk/src.libnames.mk
+++ share/mk/src.libnames.mk
@@ -44,6 +44,7 @@
fifolog \
ifconfig \
ipf \
+ iscsiutil \
lpr \
lua \
lutok \
@@ -556,6 +557,9 @@
LIBIPFDIR= ${_LIB_OBJTOP}/sbin/ipf/libipf
LIBIPF?= ${LIBIPFDIR}/libipf${PIE_SUFFIX}.a
+LIBISCSIUTILDIR= ${_LIB_OBJTOP}/lib/libiscsiutil
+LIBISCSIUTIL?= ${LIBISCSIUTILDIR}/libiscsiutil${PIE_SUFFIX}.a
+
LIBTELNETDIR= ${_LIB_OBJTOP}/lib/libtelnet
LIBTELNET?= ${LIBTELNETDIR}/libtelnet${PIE_SUFFIX}.a
Index: usr.sbin/ctld/Makefile
===================================================================
--- usr.sbin/ctld/Makefile
+++ usr.sbin/ctld/Makefile
@@ -7,16 +7,17 @@
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
Index: usr.sbin/ctld/ctld.h
===================================================================
--- usr.sbin/ctld/ctld.h
+++ 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 @@
#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 @@
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_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);
+void login(struct ctld_connection *conn);
-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 discovery(struct ctld_connection *conn);
-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 *);
bool valid_iscsi_name(const char *name);
void set_timeout(int timeout, int fatal);
-bool timed_out(void);
#endif /* !CTLD_H */
Index: usr.sbin/ctld/ctld.c
===================================================================
--- usr.sbin/ctld/ctld.c
+++ usr.sbin/ctld/ctld.c
@@ -54,6 +54,13 @@
#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 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 @@
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 @@
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 @@
return (cumulated_error);
}
-bool
+static bool
timed_out(void)
{
@@ -2407,7 +2443,7 @@
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];
Index: usr.sbin/ctld/discovery.c
===================================================================
--- usr.sbin/ctld/discovery.c
+++ usr.sbin/ctld/discovery.c
@@ -211,7 +211,7 @@
}
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 @@
}
void
-discovery(struct connection *conn)
+discovery(struct ctld_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
@@ -285,7 +285,7 @@
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 @@
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);
Index: usr.sbin/ctld/kernel.c
===================================================================
--- usr.sbin/ctld/kernel.c
+++ usr.sbin/ctld/kernel.c
@@ -893,7 +893,7 @@
}
void
-kernel_handoff(struct connection *conn)
+kernel_handoff(struct ctld_connection *conn)
{
struct ctl_iscsi req;
@@ -919,27 +919,28 @@
}
#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; "
Index: usr.sbin/ctld/login.c
===================================================================
--- usr.sbin/ctld/login.c
+++ usr.sbin/ctld/login.c
@@ -401,7 +401,7 @@
}
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 @@
* 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 @@
* 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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
* 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 @@
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 @@
* 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 @@
}
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 @@
}
void
-login(struct connection *conn)
+login(struct ctld_connection *conn)
{
struct pdu *request, *response;
struct iscsi_bhs_login_request *bhslr;
@@ -850,7 +851,7 @@
* 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);
Index: usr.sbin/iscsid/Makefile
===================================================================
--- usr.sbin/iscsid/Makefile
+++ 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>
Index: usr.sbin/iscsid/chap.c
===================================================================
--- 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);
-}
Index: usr.sbin/iscsid/discovery.c
===================================================================
--- usr.sbin/iscsid/discovery.c
+++ usr.sbin/iscsid/discovery.c
@@ -138,7 +138,7 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
#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");
Index: usr.sbin/iscsid/iscsid.h
===================================================================
--- usr.sbin/iscsid/iscsid.h
+++ 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;
-};
+void login(struct iscsid_connection *ic);
-#define KEYS_MAX 1024
+void discovery(struct iscsid_connection *ic);
-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 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 *);
-bool timed_out(void);
void fail(const struct connection *, const char *);
#endif /* !ISCSID_H */
Index: usr.sbin/iscsid/iscsid.c
===================================================================
--- usr.sbin/iscsid/iscsid.c
+++ usr.sbin/iscsid/iscsid.c
@@ -57,10 +57,25 @@
#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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
}
}
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 @@
}
static void
-handoff(struct connection *conn)
+handoff(struct iscsid_connection *conn)
{
struct iscsi_daemon_handoff idh;
int error;
@@ -357,22 +416,22 @@
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 @@
}
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 @@
* 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 @@
log_warnx("Capsicum capability mode not supported");
}
-bool
+static bool
timed_out(void)
{
@@ -519,7 +580,7 @@
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') {
Index: usr.sbin/iscsid/keys.c
===================================================================
--- 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);
-}
Index: usr.sbin/iscsid/log.c
===================================================================
--- 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);
-}
Index: usr.sbin/iscsid/login.c
===================================================================
--- usr.sbin/iscsid/login.c
+++ usr.sbin/iscsid/login.c
@@ -160,7 +160,7 @@
}
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 @@
* 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
"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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
}
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 @@
*/
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 @@
}
void
-login(struct connection *conn)
+login(struct iscsid_connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
@@ -777,7 +780,8 @@
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 @@
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 @@
}
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");
}
Index: usr.sbin/iscsid/pdu.c
===================================================================
--- 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);
-}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, May 1, 9:50 AM (17 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17878878
Default Alt Text
D33544.id100436.diff (85 KB)
Attached To
Mode
D33544: Add a new libiscsiutil library.
Attached
Detach File
Event Timeline
Log In to Comment