Exemplo n.º 1
0
static struct mbuf *
icl_conn_receive(struct icl_conn *ic, size_t len)
{
	struct uio uio;
	struct socket *so;
	struct mbuf *m;
	int error, flags;

	so = ic->ic_socket;

	memset(&uio, 0, sizeof(uio));
	uio.uio_resid = len;

	flags = MSG_DONTWAIT;
	error = soreceive(so, NULL, &uio, &m, NULL, &flags);
	if (error != 0) {
		ICL_DEBUG("soreceive error %d", error);
		return (NULL);
	}
	if (uio.uio_resid != 0) {
		m_freem(m);
		ICL_DEBUG("short read");
		return (NULL);
	}

	return (m);
}
Exemplo n.º 2
0
static int
icl_conn_receive_buf(struct icl_conn *ic, void *buf, size_t len)
{
	struct iovec iov[1];
	struct uio uio;
	struct socket *so;
	int error, flags;

	so = ic->ic_socket;

	memset(&uio, 0, sizeof(uio));
	iov[0].iov_base = buf;
	iov[0].iov_len = len;
	uio.uio_iov = iov;
	uio.uio_iovcnt = 1;
	uio.uio_offset = 0;
	uio.uio_resid = len;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_rw = UIO_READ;

	flags = MSG_DONTWAIT;
	error = soreceive(so, NULL, &uio, NULL, NULL, &flags);
	if (error != 0) {
		ICL_DEBUG("soreceive error %d", error);
		return (-1);
	}
	if (uio.uio_resid != 0) {
		ICL_DEBUG("short read");
		return (-1);
	}

	return (0);
}
Exemplo n.º 3
0
static int
icl_pdu_check_header_digest(struct icl_pdu *request, size_t *availablep)
{
	struct mbuf *m;
	uint32_t received_digest, valid_digest;

	if (request->ip_conn->ic_header_crc32c == false)
		return (0);

	m = icl_conn_receive(request->ip_conn, ISCSI_HEADER_DIGEST_SIZE);
	if (m == NULL) {
		ICL_DEBUG("failed to receive header digest");
		return (-1);
	}

	CTASSERT(sizeof(received_digest) == ISCSI_HEADER_DIGEST_SIZE);
	m_copydata(m, 0, ISCSI_HEADER_DIGEST_SIZE, (void *)&received_digest);
	m_freem(m);

	*availablep -= ISCSI_HEADER_DIGEST_SIZE;

	/*
	 * XXX: Handle AHS.
	 */
	valid_digest = icl_mbuf_to_crc32c(request->ip_bhs_mbuf);
	if (received_digest != valid_digest) {
		ICL_WARN("header digest check failed; got 0x%x, "
		    "should be 0x%x", received_digest, valid_digest);
		return (-1);
	}

	return (0);
}
Exemplo n.º 4
0
static int
icl_pdu_receive_bhs(struct icl_pdu *request, size_t *availablep)
{
	struct mbuf *m;

	m = icl_conn_receive(request->ip_conn, sizeof(struct iscsi_bhs));
	if (m == NULL) {
		ICL_DEBUG("failed to receive BHS");
		return (-1);
	}

	request->ip_bhs_mbuf = m_pullup(m, sizeof(struct iscsi_bhs));
	if (request->ip_bhs_mbuf == NULL) {
		ICL_WARN("m_pullup failed");
		return (-1);
	}
	request->ip_bhs = mtod(request->ip_bhs_mbuf, struct iscsi_bhs *);

	/*
	 * XXX: For architectures with strict alignment requirements
	 * 	we may need to allocate ip_bhs and copy the data into it.
	 * 	For some reason, though, not doing this doesn't seem
	 * 	to cause problems; tested on sparc64.
	 */

	*availablep -= sizeof(struct iscsi_bhs);
	return (0);
}
Exemplo n.º 5
0
void
icl_listen_free(struct icl_listen *il)
{
	struct icl_listen_sock *ils;

	sx_xlock(&il->il_lock);
	while (!TAILQ_EMPTY(&il->il_sockets)) {
		ils = TAILQ_FIRST(&il->il_sockets);
		while (ils->ils_running) {
			ICL_DEBUG("waiting for accept thread to terminate");
			sx_xunlock(&il->il_lock);
			ils->ils_disconnecting = true;
			wakeup(&ils->ils_socket->so_timeo);
			pause("icl_unlisten", 1 * hz);
			sx_xlock(&il->il_lock);
		}
	
		TAILQ_REMOVE(&il->il_sockets, ils, ils_next);
		soclose(ils->ils_socket);
		free(ils, M_ICL_PROXY);
	}
	sx_xunlock(&il->il_lock);

	free(il, M_ICL_PROXY);
}
Exemplo n.º 6
0
static int
icl_pdu_check_header_digest(struct icl_pdu *request, size_t *availablep)
{
	uint32_t received_digest, valid_digest;

	if (request->ip_conn->ic_header_crc32c == false)
		return (0);

	CTASSERT(sizeof(received_digest) == ISCSI_HEADER_DIGEST_SIZE);
	if (icl_conn_receive_buf(request->ip_conn,
	    &received_digest, ISCSI_HEADER_DIGEST_SIZE)) {
		ICL_DEBUG("failed to receive header digest");
		return (-1);
	}
	*availablep -= ISCSI_HEADER_DIGEST_SIZE;

	/* Temporary attach AHS to BHS to calculate header digest. */
	request->ip_bhs_mbuf->m_next = request->ip_ahs_mbuf;
	valid_digest = icl_mbuf_to_crc32c(request->ip_bhs_mbuf);
	request->ip_bhs_mbuf->m_next = NULL;
	if (received_digest != valid_digest) {
		ICL_WARN("header digest check failed; got 0x%x, "
		    "should be 0x%x", received_digest, valid_digest);
		return (-1);
	}

	return (0);
}
Exemplo n.º 7
0
static int
icl_pdu_receive_bhs(struct icl_pdu *request, size_t *availablep)
{

	if (icl_conn_receive_buf(request->ip_conn,
	    request->ip_bhs, sizeof(struct iscsi_bhs))) {
		ICL_DEBUG("failed to receive BHS");
		return (-1);
	}

	*availablep -= sizeof(struct iscsi_bhs);
	return (0);
}
Exemplo n.º 8
0
int
icl_conn_connect(struct icl_conn *ic, bool rdma, int domain, int socktype,
    int protocol, struct sockaddr *from_sa, struct sockaddr *to_sa)
{

	if (rdma) {
#ifdef ICL_RDMA
		return (icl_conn_connect_rdma(ic, domain, socktype, protocol, from_sa, to_sa));
#else
		ICL_DEBUG("RDMA not supported");
		return (EOPNOTSUPP);
#endif
	}

	return (icl_conn_connect_tcp(ic, domain, socktype, protocol, from_sa, to_sa));
}
Exemplo n.º 9
0
static int
icl_pdu_receive_ahs(struct icl_pdu *request, size_t *availablep)
{

	request->ip_ahs_len = icl_pdu_ahs_length(request);
	if (request->ip_ahs_len == 0)
		return (0);

	request->ip_ahs_mbuf = icl_conn_receive(request->ip_conn,
	    request->ip_ahs_len);
	if (request->ip_ahs_mbuf == NULL) {
		ICL_DEBUG("failed to receive AHS");
		return (-1);
	}

	*availablep -= request->ip_ahs_len;
	return (0);
}
Exemplo n.º 10
0
int
icl_listen_add(struct icl_listen *il, bool rdma, int domain, int socktype,
    int protocol, struct sockaddr *sa, int portal_id)
{

	if (rdma) {
#ifndef ICL_RDMA
		ICL_DEBUG("RDMA not supported");
		return (EOPNOTSUPP);
#else
		return (icl_listen_add_rdma(il, domain, socktype, protocol,
		    sa, portal_id));
#endif
	}


	return (icl_listen_add_tcp(il, domain, socktype, protocol, sa,
	    portal_id));
}
Exemplo n.º 11
0
/*
 * XXX: Doing accept in a separate thread in each socket might not be the best way
 * 	to do stuff, but it's pretty clean and debuggable - and you probably won't
 * 	have hundreds of listening sockets anyway.
 */
static void
icl_accept_thread(void *arg)
{
	struct icl_listen_sock *ils;
	struct socket *head, *so;
	struct sockaddr *sa;
	int error;

	ils = arg;
	head = ils->ils_socket;

	ils->ils_running = true;

	for (;;) {
		ACCEPT_LOCK();
		while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0 && ils->ils_disconnecting == false) {
			if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
				head->so_error = ECONNABORTED;
				break;
			}
			error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
			    "accept", 0);
			if (error) {
				ACCEPT_UNLOCK();
				ICL_WARN("msleep failed with error %d", error);
				continue;
			}
			if (ils->ils_disconnecting) {
				ACCEPT_UNLOCK();
				ICL_DEBUG("terminating");
				ils->ils_running = false;
				kthread_exit();
				return;
			}
		}
		if (head->so_error) {
			error = head->so_error;
			head->so_error = 0;
			ACCEPT_UNLOCK();
			ICL_WARN("socket error %d", error);
			continue;
		}
		so = TAILQ_FIRST(&head->so_comp);
		KASSERT(so != NULL, ("NULL so"));
		KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
		KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));

		/*
		 * Before changing the flags on the socket, we have to bump the
		 * reference count.  Otherwise, if the protocol calls sofree(),
		 * the socket will be released due to a zero refcount.
		 */
		SOCK_LOCK(so);			/* soref() and so_state update */
		soref(so);			/* file descriptor reference */

		TAILQ_REMOVE(&head->so_comp, so, so_list);
		head->so_qlen--;
		so->so_state |= (head->so_state & SS_NBIO);
		so->so_qstate &= ~SQ_COMP;
		so->so_head = NULL;

		SOCK_UNLOCK(so);
		ACCEPT_UNLOCK();

		sa = NULL;
		error = soaccept(so, &sa);
		if (error != 0) {
			ICL_WARN("soaccept error %d", error);
			if (sa != NULL)
				free(sa, M_SONAME);
			soclose(so);
			continue;
		}

		(ils->ils_listen->il_accept)(so, sa, ils->ils_id);
	}
}