diff options
Diffstat (limited to 'usr.sbin/iscsid')
| -rw-r--r-- | usr.sbin/iscsid/Makefile | 5 | ||||
| -rw-r--r-- | usr.sbin/iscsid/chap.c | 423 | ||||
| -rw-r--r-- | usr.sbin/iscsid/discovery.c | 14 | ||||
| -rw-r--r-- | usr.sbin/iscsid/iscsid.c | 173 | ||||
| -rw-r--r-- | usr.sbin/iscsid/iscsid.h | 97 | ||||
| -rw-r--r-- | usr.sbin/iscsid/keys.c | 199 | ||||
| -rw-r--r-- | usr.sbin/iscsid/log.c | 202 | ||||
| -rw-r--r-- | usr.sbin/iscsid/login.c | 74 | ||||
| -rw-r--r-- | usr.sbin/iscsid/pdu.c | 309 |
9 files changed, 171 insertions, 1325 deletions
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); -} |
