Ejemplo n.º 1
0
static int recv_challenge_reply (int fd, 
				 unsigned our_challenge,
				 char cookie[], 
				 unsigned *her_challenge,
				 unsigned ms)
{
    char dbuf[DEFBUF_SIZ];
    char *buf = dbuf;
    int is_static = 1;
    int buflen = DEFBUF_SIZ;
    int rlen;
    char *s;
    char tag;
    char her_digest[16], expected_digest[16];
    
    erl_errno = EIO;		/* Default */

    if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 21) {
	EI_TRACE_ERR1("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY socket read failed (%d)",rlen);
	goto error;
    }
    
    s = buf;
    if ((tag = get8(s)) != 'r') {
	EI_TRACE_ERR2("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY incorrect tag, "
		      "expected 'r' got '%c' (%u)",tag,tag);
	goto error;
    }
    *her_challenge = get32be(s);
    memcpy(her_digest, s, 16);
    gen_digest(our_challenge, cookie, (unsigned char*)expected_digest);
    if (memcmp(her_digest, expected_digest, 16)) {
	EI_TRACE_ERR0("recv_challenge_reply",
		      "<- RECV_CHALLENGE_REPLY authorization failure");
	goto error;
    }
    if (!is_static)
	free(buf);

   
    if (ei_tracelevel >= 3) {
	char buffer[33];	
        EI_TRACE_CONN2("recv_challenge_reply",
		   "<- RECV_CHALLENGE_REPLY (ok) challenge = %u, digest = %s",
		   *her_challenge,hex(her_digest,buffer));
    }
    erl_errno = 0;
    return 0;
    
error:
    if (!is_static)
	free(buf);
    return -1;
}
Ejemplo n.º 2
0
int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
{
    int fd;
    struct sockaddr_in cli_addr;
    int cli_addr_len=sizeof(struct sockaddr_in);
    unsigned her_version, her_flags;
    ErlConnect her_name;

    erl_errno = EIO;		/* Default error code */

    EI_TRACE_CONN0("ei_accept","<- ACCEPT waiting for connection");
    
    if ((fd = ei_accept_t(lfd, (struct sockaddr*) &cli_addr, 
	&cli_addr_len, ms )) < 0) {
	EI_TRACE_ERR0("ei_accept","<- ACCEPT socket accept failed");
	erl_errno = (fd == -2) ? ETIMEDOUT : EIO;
	goto error;
    }
    
    EI_TRACE_CONN0("ei_accept","<- ACCEPT connected to remote");
    
    if (recv_name(fd, &her_version, &her_flags, &her_name, ms)) {
	EI_TRACE_ERR0("ei_accept","<- ACCEPT initial ident failed");
	goto error;
    }
    
    if (her_version <= 4) {
	EI_TRACE_ERR0("ei_accept","<- ACCEPT remote version not compatible");
	goto error;
    }
    else {
	unsigned our_challenge;
	unsigned her_challenge;
	unsigned char our_digest[16];
	
	if (send_status(fd,"ok", ms))
	    goto error;
	our_challenge = gen_challenge();
	if (send_challenge(fd, ec->thisnodename, 
	    our_challenge, her_version, ms))
	    goto error;
	if (recv_challenge_reply(fd, our_challenge, 
	    ec->ei_connect_cookie, 
	    &her_challenge, ms))
	    goto error;
	gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
	if (send_challenge_ack(fd, our_digest, ms))
	    goto error;
	put_ei_socket_info(fd, her_version, null_cookie, ec);
    }
    if (conp) 
	*conp = her_name;
    
    EI_TRACE_CONN1("ei_accept","<- ACCEPT (ok) remote = %s",her_name.nodename);

    erl_errno = 0;		/* No error */
    return fd;
    
error:
    EI_TRACE_ERR0("ei_accept","<- ACCEPT failed");
    closesocket(fd);
    return ERL_ERROR;
} /* ei_accept */
Ejemplo n.º 3
0
 /* ip_addr is now in network byte order 
  *
  * first we have to get hold of the portnumber to
  *  the node through epmd at that host 
  *
*/
int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms)
{
    struct in_addr *ip_addr=(struct in_addr *) adr;
    int rport = 0; /*uint16 rport = 0;*/
    int sockd;
    int one = 1;
    int dist = 0;
    ErlConnect her_name;
    unsigned her_flags, her_version;

    erl_errno = EIO;		/* Default error code */
    
    EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to %s",
		   alivename);
    
    if ((rport = ei_epmd_port_tmo(ip_addr,alivename,&dist, ms)) < 0) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT can't get remote port");
	/* ei_epmd_port_tmo() has set erl_errno */
	return ERL_NO_PORT;
    }
    
    /* we now have port number to enode, try to connect */
    if((sockd = cnct((uint16)rport, ip_addr, sizeof(struct in_addr),ms)) < 0) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT socket connect failed");
	/* cnct() has set erl_errno */
	return ERL_CONNECT_FAIL;
    }
    
    EI_TRACE_CONN0("ei_xconnect","-> CONNECT connected to remote");

    /* FIXME why connect before checking 'dist' output from ei_epmd_port() ?! */
    if (dist <= 4) {
	EI_TRACE_ERR0("ei_xconnect","-> CONNECT remote version not compatible");
	goto error;
    }
    else {
	unsigned our_challenge, her_challenge;
	unsigned char our_digest[16];
	
	if (send_name(sockd, ec->thisnodename, (unsigned) dist, ms))
	    goto error;
	if (recv_status(sockd, ms))
	    goto error;
	if (recv_challenge(sockd, &her_challenge, &her_version,
	    &her_flags, &her_name, ms))
	    goto error;
	our_challenge = gen_challenge();
	gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
	if (send_challenge_reply(sockd, our_digest, our_challenge, ms))
	    goto error;
	if (recv_challenge_ack(sockd, our_challenge, 
	    ec->ei_connect_cookie, ms))
	    goto error;
	put_ei_socket_info(sockd, dist, null_cookie, ec); /* FIXME check == 0 */
    }
    
    setsockopt(sockd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
    setsockopt(sockd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof(one));

    EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename);
    
    erl_errno = 0;
    return sockd;
    
error:
    EI_TRACE_ERR0("ei_xconnect","-> CONNECT failed");
    closesocket(sockd);
    return ERL_ERROR;
} /* ei_xconnect */
Ejemplo n.º 4
0
void
test_send_pdu(struct proc *p, iscsi_test_send_pdu_parameters_t *par)
{
	static uint8_t pad_bytes[4] = { 0 };
	test_pars_t *tp;
	connection_t *conn;
	pdu_t *pdu;
	uint32_t psize = par->pdu_size;
	void *pdu_ptr = par->pdu_ptr;
	struct uio *uio;
	uint32_t i, pad, dsl, size;
	int s;

	if ((tp = find_test_id(par->test_id)) == NULL) {
		par->status = ISCSI_STATUS_INVALID_ID;
		return;
	}
	if (!psize || pdu_ptr == NULL ||
		((par->options & ISCSITEST_SFLAG_UPDATE_FIELDS) && psize < BHS_SIZE)) {
		par->status = ISCSI_STATUS_PARAMETER_INVALID;
		return;
	}
	if ((conn = tp->connection) == NULL) {
		par->status = ISCSI_STATUS_TEST_INACTIVE;
		return;
	}
	if ((pdu = get_pdu(conn, TRUE)) == NULL) {
		par->status = ISCSI_STATUS_TEST_CONNECTION_CLOSED;
		return;
	}
	DEB(1, ("Test Send PDU, id %d\n", par->test_id));

	if ((par->status = map_databuf(p, &pdu_ptr, psize)) != 0) {
		free_pdu(pdu);
		return;
	}

	i = 1;
	if (!par->options) {
		pdu->io_vec[0].iov_base = pdu_ptr;
		pdu->io_vec[0].iov_len = size = psize;
	} else {
		memcpy(&pdu->pdu, pdu_ptr, BHS_SIZE);

		if (!(pdu->pdu.Opcode & OP_IMMEDIATE))
			conn->session->CmdSN++;
		pdu->pdu.p.command.CmdSN = htonl(conn->session->CmdSN);

		dsl = psize - BHS_SIZE;
		size = BHS_SIZE;

		hton3(dsl, pdu->pdu.DataSegmentLength);

		if (conn->HeaderDigest &&
			!(par->options & ISCSITEST_SFLAG_NO_HEADER_DIGEST)) {
			pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
			size += 4;
		}

		pdu->io_vec[0].iov_base = &pdu->pdu;
		pdu->io_vec[0].iov_len = size;

		if (dsl) {
			pdu->io_vec[1].iov_base = &pdu_ptr[BHS_SIZE];
			pdu->io_vec[1].iov_len = dsl;
			i++;
			size += dsl;

			/* Pad to next multiple of 4 */
			pad = (par->options & ISCSITEST_SFLAG_NO_PADDING) ? 0 : size & 0x03;

			if (pad) {
				pad = 4 - pad;
				pdu->io_vec[i].iov_base = pad_bytes;
				pdu->io_vec[i].iov_len = pad;
				i++;
				size += pad;
			}

			if (conn->DataDigest &&
				!(par->options & ISCSITEST_SFLAG_NO_DATA_DIGEST)) {
				pdu->data_digest = gen_digest_2(&pdu_ptr[BHS_SIZE], dsl,
												pad_bytes, pad);
				pdu->io_vec[i].iov_base = &pdu->data_digest;
				pdu->io_vec[i].iov_len = 4;
				i++;
				size += 4;
			}
		}
	}
	uio = &pdu->uio;
	uio->uio_iov = pdu->io_vec;
	UIO_SETUP_SYSSPACE(uio);
	uio->uio_rw = UIO_WRITE;
	uio->uio_iovcnt = i;
	uio->uio_resid = size;

	pdu->disp = PDUDISP_SIGNAL;
	pdu->flags = PDUF_BUSY | PDUF_NOUPDATE;

	s = splbio();
	/* Enqueue for sending */
	if (pdu->pdu.Opcode & OP_IMMEDIATE)
		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
	else
		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);

	wakeup(&conn->pdus_to_send);
	tsleep(pdu, PINOD, "test_send_pdu", 0);
	splx(s);

	unmap_databuf(p, pdu_ptr, psize);
	par->status = ISCSI_STATUS_SUCCESS;
	if (par->options & ISCSITEST_KILL_CONNECTION)
		kill_connection(conn, ISCSI_STATUS_TEST_CONNECTION_CLOSED, NO_LOGOUT,
						TRUE);
}
Ejemplo n.º 5
0
STATIC int
test_mod(test_pars_t *tp, pdu_t *pdu, iscsi_pdu_kind_t kind, int rxtx, int err)
{
	mod_desc_t *mod;
	uint32_t mpoff, off;
	int i, rc = 0, s;

	tp->pdu_count[kind][rxtx]++;
	tp->pdu_count[ANY_PDU][rxtx]++;

	do {
		if ((mod = TAILQ_FIRST(&tp->mods)) == NULL) {
			return check_loss(tp, rxtx);
		}
		if (mod->pars.which_pdu != ANY_PDU &&
		    mod->pars.which_pdu != kind) {
			return check_loss(tp, rxtx);
		}
		mpoff = mod->pars.pdu_offset;

		switch (mod->pars.which_offset) {
		case ABSOLUTE_ANY:
			off = tp->pdu_count[ANY_PDU][CNT_TX] +
				  tp->pdu_count[ANY_PDU][CNT_RX];
			break;
		case RELATIVE_ANY:
			off = (tp->pdu_count[ANY_PDU][CNT_TX] +
				   tp->pdu_count[ANY_PDU][CNT_RX]) -
				(tp->pdu_last[ANY_PDU][CNT_TX] + tp->pdu_last[ANY_PDU][CNT_RX]);
			break;

		case ABSOLUTE_PDUKIND:
			off = tp->pdu_count[kind][rxtx];
			break;
		case RELATIVE_PDUKIND:
			off = tp->pdu_count[kind][rxtx] - tp->pdu_last[kind][rxtx];
			break;

		case ABSOLUTE_TX:
			if (rxtx != CNT_TX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_TX];
			break;
		case RELATIVE_TX:
			if (rxtx != CNT_TX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_TX] -
				  tp->pdu_last[ANY_PDU][CNT_TX];
			break;

		case ABSOLUTE_RX:
			if (rxtx != CNT_RX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_RX];
			break;
		case RELATIVE_RX:
			if (rxtx != CNT_RX)
				return check_loss(tp, rxtx);
			off = tp->pdu_count[ANY_PDU][CNT_RX] -
				  tp->pdu_last[ANY_PDU][CNT_RX];
			break;

		default:
			/* bad offset - skip this entry */
			mpoff = off = 0;
			break;
		}

		DEB(1, ("test_mod: kind=%d, rxtx=%d, pdukind=%d, mpoff=%d, "
				"whichoff=%d, off=%d\n", kind, rxtx, mod->pars.which_pdu,
				mpoff, mod->pars.which_offset, off));

		if (!off || (mpoff != 0 && mpoff < off)) {
			/* This might happen in some cases. Just discard the modification. */
			s = splbio();
			TAILQ_REMOVE(&tp->mods, mod, link);
			splx(s);

			update_options(tp, mod);

			if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
				mod->pars.status = ISCSI_STATUS_TEST_MODIFICATION_SKIPPED;
				wakeup(mod);
			}
			free(mod, M_TEMP);
		}
	} while (mpoff && mpoff < off);

	if (mpoff > off)
		return check_loss(tp, rxtx);

	DEB(1, ("test_mod: opt=%x, pdu_ptr=%x, num_mods=%d\n", mod->pars.options,
			(int) mod->pdu_ptr, mod->pars.num_pdu_mods));

	if (mod->pdu_ptr)
		test_get(pdu, mod, err);

	if (mod->pars.options & ISCSITEST_OPT_DISCARD_PDU)
		rc = 1;
	else if (check_loss(tp, rxtx))
		rc = 1;
	else if (mod->pars.num_pdu_mods) {
		if (!(mod->pars.options & ISCSITEST_OPT_MOD_PERMANENT)) {
			/*
             * Note: if the PDU is later resent, the unmodified one will be
             * used as resend_pdu restores the original io vector.
             */
			pdu->mod_pdu = pdu->pdu;
			pdu->io_vec[0].iov_base = &pdu->mod_pdu;
		}
		for (i = 0; i < mod->pars.num_pdu_mods; i++) {
			mod_pdu(pdu, &mod->mods[i]);
		}
	}

	if (rxtx == CNT_TX) {
		if (mod->pars.options & ISCSITEST_OPT_NO_RESPONSE_PDU) {
			ccb_t *ccb = pdu->owner;

			DEB(1, ("test_mod: No response expected, completing CCB %x\n",
					(int)ccb));

			if (ccb != NULL &&
				(ccb->disp == CCBDISP_WAIT || ccb->disp == CCBDISP_SCSIPI)) {
				/* simulate timeout */
				wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
			}
		}

		if ((mod->pars.options & ISCSITEST_SFLAG_UPDATE_FIELDS) &&
			mod->pars.num_pdu_mods) {
			connection_t *conn = pdu->connection;

			if (conn->HeaderDigest &&
				!(mod->pars.options & ISCSITEST_SFLAG_NO_HEADER_DIGEST))
				pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);

			if (pdu->uio.uio_iovcnt > 1 && conn->DataDigest &&
				!(mod->pars.options & ISCSITEST_SFLAG_NO_DATA_DIGEST))
				pdu->data_digest = gen_digest_2(
						pdu->io_vec[1].iov_base,
						pdu->io_vec[1].iov_len,
						pdu->io_vec[2].iov_base,
						pdu->io_vec[2].iov_len);
		}
	}

	s = splbio();
	TAILQ_REMOVE(&tp->mods, mod, link);
	update_options(tp, mod);
	/* we've modified a PDU - copy current count into last count */
	memcpy(tp->pdu_last, tp->pdu_count, sizeof(tp->pdu_last));
	splx(s);

	if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
		wakeup(mod);
	}
	if (mod->pars.options & ISCSITEST_KILL_CONNECTION) {
		kill_connection(tp->connection,
				ISCSI_STATUS_TEST_CONNECTION_CLOSED,
				NO_LOGOUT, TRUE);
	}
	free(mod, M_TEMP);

	return rc;
}