コード例 #1
0
ファイル: iconv.c プロジェクト: angcoch/freetds
static int
get_ucs4le(const unsigned char *p, size_t len, ICONV_CHAR *out)
{
	if (len < 4)
		return -EINVAL;
	*out = TDS_GET_A4LE(p);
	return 4;
}
コード例 #2
0
ファイル: read.c プロジェクト: Distrotech/freetds
/**
 * Get an int32 from the server.
 */
TDS_INT
tds_get_int(TDSSOCKET * tds)
{
	unsigned char bytes[4];

	tds_get_n(tds, bytes, 4);
#if WORDS_BIGENDIAN
	if (tds->emul_little_endian)
		return (TDS_INT) TDS_GET_A4LE(bytes);
#endif
	return (TDS_INT) TDS_GET_A4(bytes);
}
コード例 #3
0
ファイル: read.c プロジェクト: DavidRueter/freetds
/**
 * Get an int32 from the server.
 * \tds
 */
TDS_UINT
tds_get_uint(TDSSOCKET * tds)
{
	TDS_UINT bytes;

	tds_get_n(tds, &bytes, 4);
#if WORDS_BIGENDIAN
	if (tds->conn->emul_little_endian)
		return TDS_GET_A4LE(&bytes);
#endif
	return TDS_GET_A4(&bytes);
}
コード例 #4
0
ファイル: read.c プロジェクト: Distrotech/freetds
TDS_INT8
tds_get_int8(TDSSOCKET * tds)
{
	TDS_INT h;
	TDS_UINT l;
	unsigned char bytes[8];

	tds_get_n(tds, bytes, 8);
#if WORDS_BIGENDIAN
	if (tds->emul_little_endian) {
		l = TDS_GET_A4LE(bytes);
		h = (TDS_INT) TDS_GET_A4LE(bytes+4);
	} else {
		h = (TDS_INT) TDS_GET_A4(bytes);
		l = TDS_GET_A4(bytes+4);
	}
#else
	l = TDS_GET_A4(bytes);
	h = (TDS_INT) TDS_GET_A4(bytes+4);
#endif
	return (((TDS_INT8) h) << 32) | l;
}
コード例 #5
0
ファイル: read.c プロジェクト: DavidRueter/freetds
/**
 * Get an uint64 from the server.
 * \tds
 */
TDS_UINT8
tds_get_uint8(TDSSOCKET * tds)
{
	TDS_UINT h;
	TDS_UINT l;
	TDS_UINT bytes[2];

	tds_get_n(tds, bytes, 8);
#if WORDS_BIGENDIAN
	if (tds->conn->emul_little_endian) {
		l = TDS_GET_A4LE(bytes);
		h = TDS_GET_A4LE(bytes+1);
	} else {
		h = TDS_GET_A4(bytes);
		l = TDS_GET_A4(bytes+1);
	}
#else
	l = TDS_GET_A4(bytes);
	h = TDS_GET_A4(bytes+1);
#endif
	return (((TDS_UINT8) h) << 32) | l;
}
コード例 #6
0
ファイル: packet.c プロジェクト: FreeTDS/freetds
/* read partial packet */
static void
tds_packet_read(TDSCONNECTION *conn, TDSSOCKET *tds)
{
	TDSPACKET *packet = conn->recv_packet;
	int len;

	/* allocate some space to read data */
	if (!packet) {
		conn->recv_packet = packet = tds_get_packet(conn, MAX(conn->env.block_size + sizeof(TDS72_SMP_HEADER), 512));
		if (!packet) goto Memory_Error;
		TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
		conn->recv_pos = 0;
		packet->len = 8;
	}

	assert(conn->recv_pos < packet->len && packet->len <= packet->capacity);

	len = tds_connection_read(tds, packet->buf + conn->recv_pos, packet->len - conn->recv_pos);
	if (len < 0)
		goto Severe_Error;
	conn->recv_pos += len;
	assert(conn->recv_pos <= packet->len && packet->len <= packet->capacity);

	/* handle SMP */
	if (conn->recv_pos > 0 && packet->buf[0] == TDS72_SMP) {
		TDS72_SMP_HEADER mars_header;
		short sid;
		TDSSOCKET *tds;
		TDS_UINT size;

		if (conn->recv_pos < 16) {
			packet->len = 16;
			return;
		}

		memcpy(&mars_header, packet->buf, sizeof(mars_header));
		tdsdump_dump_buf(TDS_DBG_HEADER, "Received MARS header", &mars_header, sizeof(mars_header));
		sid = TDS_GET_A2LE(&mars_header.sid);

		/* FIXME this is done even by caller !! */
		tds = NULL;
		tds_mutex_lock(&conn->list_mtx);
		if (sid >= 0 && sid < conn->num_sessions)
			tds = conn->sessions[sid];
		tds_mutex_unlock(&conn->list_mtx);
		packet->sid = sid;

		if (tds == BUSY_SOCKET) {
			if (mars_header.type != TDS_SMP_FIN) {
				tdsdump_log(TDS_DBG_ERROR, "Received MARS with no session (%d)\n", sid);
				goto Severe_Error;
			}

			/* check if was just a "zombie" socket */
			tds_mutex_lock(&conn->list_mtx);
			conn->sessions[sid] = NULL;
			tds_mutex_unlock(&conn->list_mtx);

			/* reset packet to initial state to reuse it */
			packet->len = 8;
			conn->recv_pos = 0;
			return;
		}

		if (!tds) {
			/* server sent a unknown packet, close connection */
			goto Severe_Error;
		}

		tds->send_wnd = TDS_GET_A4LE(&mars_header.wnd);
		size = TDS_GET_A4LE(&mars_header.size);
		if (mars_header.type == TDS_SMP_ACK) {
			if (size != sizeof(mars_header))
				goto Severe_Error;
		} else if (mars_header.type == TDS_SMP_DATA) {
			if (size < 0x18 || size > 0xffffu + sizeof(mars_header))
				goto Severe_Error;
			/* avoid recursive SMP */
			if (conn->recv_pos > 16 && packet->buf[16] == TDS72_SMP)
				goto Severe_Error;
			/* TODO is possible to put 2 TDS packet inside a single DATA ?? */
			if (conn->recv_pos >= 20 && TDS_GET_A2BE(&packet->buf[18]) != size - 16)
				goto Severe_Error;
			tds->recv_seq = TDS_GET_A4LE(&mars_header.seq);
			/*
			 * does not sent ACK here cause this would lead to memory waste
			 * if session is not able to handle all that packets
			 */
		} else if (mars_header.type == TDS_SMP_FIN) {
			if (size != sizeof(mars_header))
				goto Severe_Error;
			/* this socket shold now not start another session */
//			tds_set_state(tds, TDS_DEAD);
//			tds->sid = -1;
		} else
			goto Severe_Error;

		if (mars_header.type != TDS_SMP_DATA)
			return;
		if (packet->len < size) {
			packet = tds_realloc_packet(packet, size);
			if (!packet) goto Memory_Error;
			conn->recv_packet = packet;
		}
		packet->len = size;
		return;
	}
	assert(conn->recv_pos <= packet->len && packet->len <= packet->capacity);

	/* normal packet */
	if (conn->recv_pos >= 8) {
		len = TDS_GET_A2BE(&packet->buf[2]);
		if (len < 8)
			goto Severe_Error;
		if (packet->len < len) {
			packet = tds_realloc_packet(packet, len);
			if (!packet) goto Memory_Error;
			conn->recv_packet = packet;
		}
		packet->len = len;
	}
	return;

Memory_Error:
Severe_Error:
	tds_connection_close(conn);
	tds_free_packets(packet);
	conn->recv_packet = NULL;
}