From 36e34842606b312a0ca338667797b6c00df50de7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:10:23 +0200 Subject: [PATCH] s3:smb2_server: move sconn->smb2.*credits* to xconn->smb2.credits.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Reviewed-by: Michael Adam --- source3/smbd/globals.h | 89 +++++++++++++++--------------- source3/smbd/smb2_negprot.c | 2 +- source3/smbd/smb2_server.c | 105 +++++++++++++++++++----------------- 3 files changed, 103 insertions(+), 93 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 129edbe23ae..a32f7b41baa 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -434,6 +434,52 @@ struct smbXsrv_connection { struct smbd_smb2_send_queue *send_queue; size_t send_queue_len; + struct { + /* + * seq_low is the lowest sequence number + * we will accept. + */ + uint64_t seq_low; + /* + * seq_range is the range of credits we have + * granted from the sequence windows starting + * at seq_low. + * + * This gets incremented when new credits are + * granted and gets decremented when the + * lowest sequence number is consumed + * (when seq_low gets incremented). + */ + uint16_t seq_range; + /* + * The number of credits we have currently granted + * to the client. + * + * This gets incremented when new credits are + * granted and gets decremented when any credit + * is comsumed. + * + * Note: the decrementing is different compared + * to seq_range. + */ + uint16_t granted; + /* + * The maximum number of credits we will ever + * grant to the client. + * + * Typically we will only grant 1/16th of + * max_credits. + * + * This is the "server max credits" parameter. + */ + uint16_t max; + /* + * a bitmap of size max_credits + */ + struct bitmap *bitmap; + bool multicredit; + } credits; + bool allow_2ff; struct { uint32_t capabilities; @@ -796,49 +842,6 @@ struct smbd_server_connection { bool blocking_lock_unlock_state; } locks; struct smbd_smb2_request *requests; - /* - * seqnum_low is the lowest sequence number - * we will accept. - */ - uint64_t seqnum_low; - /* - * seqnum_range is the range of credits we have - * granted from the sequence windows starting - * at seqnum_low. - * - * This gets incremented when new credits are - * granted and gets decremented when the - * lowest sequence number is consumed - * (when seqnum_low gets incremented). - */ - uint16_t seqnum_range; - /* - * credits_grantedThe number of credits we have currently granted - * to the client. - * - * This gets incremented when new credits are - * granted and gets decremented when any credit - * is comsumed. - * - * Note: the decrementing is different compared - * to seqnum_range. - */ - uint16_t credits_granted; - /* - * The maximum number of credits we will ever - * grant to the client. - * - * Typically we will only grant 1/16th of - * max_credits. - * - * This is the "server max credits" parameter. - */ - uint16_t max_credits; - /* - * a bitmap of size max_credits - */ - struct bitmap *credits_bitmap; - bool supports_multicredit; } smb2; /* diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 9d84f1ab576..fde951462cc 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -300,7 +300,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) /* largeMTU is not supported over NBT (tcp port 139) */ if (p != NBT_SMB_PORT) { capabilities |= SMB2_CAP_LARGE_MTU; - req->sconn->smb2.supports_multicredit = true; + xconn->smb2.credits.multicredit = true; /* Windows 2012R2 allows up to 8 MB */ max_limit = 0x800000; /* 8MB */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index ba0091103b7..b48d1819ba9 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -204,13 +204,13 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) TALLOC_FREE(xconn->transport.fde); - sconn->smb2.seqnum_low = 0; - sconn->smb2.seqnum_range = 1; - sconn->smb2.credits_granted = 1; - sconn->smb2.max_credits = lp_smb2_max_credits(); - sconn->smb2.credits_bitmap = bitmap_talloc(sconn, - sconn->smb2.max_credits); - if (sconn->smb2.credits_bitmap == NULL) { + xconn->smb2.credits.seq_low = 0; + xconn->smb2.credits.seq_range = 1; + xconn->smb2.credits.granted = 1; + xconn->smb2.credits.max = lp_smb2_max_credits(); + xconn->smb2.credits.bitmap = bitmap_talloc(xconn, + xconn->smb2.credits.max); + if (xconn->smb2.credits.bitmap == NULL) { return NT_STATUS_NO_MEMORY; } @@ -578,34 +578,38 @@ static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn, static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn, uint64_t message_id, uint64_t seq_id) { - struct bitmap *credits_bm = sconn->smb2.credits_bitmap; + struct smbXsrv_connection *xconn = sconn->conn; + struct bitmap *credits_bm = xconn->smb2.credits.bitmap; unsigned int offset; + uint64_t seq_tmp; - if (seq_id < sconn->smb2.seqnum_low) { + seq_tmp = xconn->smb2.credits.seq_low; + if (seq_id < seq_tmp) { DEBUG(0,("smb2_validate_sequence_number: bad message_id " "%llu (sequence id %llu) " "(granted = %u, low = %llu, range = %u)\n", (unsigned long long)message_id, (unsigned long long)seq_id, - (unsigned int)sconn->smb2.credits_granted, - (unsigned long long)sconn->smb2.seqnum_low, - (unsigned int)sconn->smb2.seqnum_range)); + (unsigned int)xconn->smb2.credits.granted, + (unsigned long long)xconn->smb2.credits.seq_low, + (unsigned int)xconn->smb2.credits.seq_range)); return false; } - if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) { + seq_tmp += xconn->smb2.credits.seq_range; + if (seq_id >= seq_tmp) { DEBUG(0,("smb2_validate_sequence_number: bad message_id " "%llu (sequence id %llu) " "(granted = %u, low = %llu, range = %u)\n", (unsigned long long)message_id, (unsigned long long)seq_id, - (unsigned int)sconn->smb2.credits_granted, - (unsigned long long)sconn->smb2.seqnum_low, - (unsigned int)sconn->smb2.seqnum_range)); + (unsigned int)xconn->smb2.credits.granted, + (unsigned long long)xconn->smb2.credits.seq_low, + (unsigned int)xconn->smb2.credits.seq_range)); return false; } - offset = seq_id % sconn->smb2.max_credits; + offset = seq_id % xconn->smb2.credits.max; if (bitmap_query(credits_bm, offset)) { DEBUG(0,("smb2_validate_sequence_number: duplicate message_id " @@ -614,9 +618,9 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn, "(bm offset %u)\n", (unsigned long long)message_id, (unsigned long long)seq_id, - (unsigned int)sconn->smb2.credits_granted, - (unsigned long long)sconn->smb2.seqnum_low, - (unsigned int)sconn->smb2.seqnum_range, + (unsigned int)xconn->smb2.credits.granted, + (unsigned long long)xconn->smb2.credits.seq_low, + (unsigned int)xconn->smb2.credits.seq_range, offset)); return false; } @@ -624,7 +628,7 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn, /* Mark the message_ids as seen in the bitmap. */ bitmap_set(credits_bm, offset); - if (seq_id != sconn->smb2.seqnum_low) { + if (seq_id != xconn->smb2.credits.seq_low) { return true; } @@ -635,13 +639,13 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn, while (bitmap_query(credits_bm, offset)) { DEBUG(10,("smb2_validate_sequence_number: clearing " "id %llu (position %u) from bitmap\n", - (unsigned long long)(sconn->smb2.seqnum_low), + (unsigned long long)(xconn->smb2.credits.seq_low), offset)); bitmap_clear(credits_bm, offset); - sconn->smb2.seqnum_low += 1; - sconn->smb2.seqnum_range -= 1; - offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits; + xconn->smb2.credits.seq_low += 1; + xconn->smb2.credits.seq_range -= 1; + offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max; } return true; @@ -650,6 +654,7 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn, static bool smb2_validate_message_id(struct smbd_server_connection *sconn, const uint8_t *inhdr) { + struct smbXsrv_connection *xconn = sconn->conn; uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID); uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE); uint16_t credit_charge = 1; @@ -660,7 +665,7 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn, return true; } - if (sconn->smb2.supports_multicredit) { + if (xconn->smb2.credits.multicredit) { credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE); credit_charge = MAX(credit_charge, 1); } @@ -670,20 +675,20 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn, "seqnum low/range: %llu/%llu\n", (unsigned long long) message_id, (unsigned long long) credit_charge, - (unsigned long long) sconn->smb2.credits_granted, - (unsigned long long) sconn->smb2.seqnum_low, - (unsigned long long) sconn->smb2.seqnum_range)); + (unsigned long long) xconn->smb2.credits.granted, + (unsigned long long) xconn->smb2.credits.seq_low, + (unsigned long long) xconn->smb2.credits.seq_range)); - if (sconn->smb2.credits_granted < credit_charge) { + if (xconn->smb2.credits.granted < credit_charge) { DEBUG(0, ("smb2_validate_message_id: client used more " "credits than granted, mid %llu, charge %llu, " "credits_granted %llu, " "seqnum low/range: %llu/%llu\n", (unsigned long long) message_id, (unsigned long long) credit_charge, - (unsigned long long) sconn->smb2.credits_granted, - (unsigned long long) sconn->smb2.seqnum_low, - (unsigned long long) sconn->smb2.seqnum_range)); + (unsigned long long) xconn->smb2.credits.granted, + (unsigned long long) xconn->smb2.credits.seq_low, + (unsigned long long) xconn->smb2.credits.seq_range)); return false; } @@ -711,7 +716,7 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn, } /* substract used credits */ - sconn->smb2.credits_granted -= credit_charge; + xconn->smb2.credits.granted -= credit_charge; return true; } @@ -760,6 +765,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, const struct iovec *in_vector, struct iovec *out_vector) { + struct smbXsrv_connection *xconn = sconn->conn; const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base; uint8_t *outhdr = (uint8_t *)out_vector->iov_base; uint16_t credit_charge = 1; @@ -785,10 +791,10 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, * Which means we would grant more credits * for client which use multi credit requests. */ - current_max_credits = sconn->smb2.max_credits / 16; + current_max_credits = xconn->smb2.credits.max / 16; current_max_credits = MAX(current_max_credits, 1); - if (sconn->smb2.supports_multicredit) { + if (xconn->smb2.credits.multicredit) { credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE); credit_charge = MAX(credit_charge, 1); } @@ -798,9 +804,9 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, out_flags = IVAL(outhdr, SMB2_HDR_FLAGS); out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS)); - SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted); + SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted); - if (sconn->smb2.max_credits < credit_charge) { + if (xconn->smb2.credits.max < credit_charge) { smbd_server_connection_terminate(sconn, "client error: credit charge > max credits\n"); return; @@ -842,7 +848,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, additional_credits = MIN(additional_credits, additional_max); credits_granted = credit_charge + additional_credits; - } else if (sconn->smb2.credits_granted == 0) { + } else if (xconn->smb2.credits.granted == 0) { /* * Make sure the client has always at least one credit */ @@ -864,19 +870,19 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, * this makes sure the client consumes the lowest sequence * number, before we can grant additional credits. */ - credits_possible = UINT64_MAX - sconn->smb2.seqnum_low; + credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low; if (credits_possible > 0) { /* remove UINT64_MAX */ credits_possible -= 1; } credits_possible = MIN(credits_possible, current_max_credits); - credits_possible -= sconn->smb2.seqnum_range; + credits_possible -= xconn->smb2.credits.seq_range; credits_granted = MIN(credits_granted, credits_possible); SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted); - sconn->smb2.credits_granted += credits_granted; - sconn->smb2.seqnum_range += credits_granted; + xconn->smb2.credits.granted += credits_granted; + xconn->smb2.credits.seq_range += credits_granted; DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, " "granted %u, current possible/max %u/%u, " @@ -886,10 +892,10 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn, (unsigned int)credits_granted, (unsigned int)credits_possible, (unsigned int)current_max_credits, - (unsigned int)sconn->smb2.credits_granted, - (unsigned int)sconn->smb2.max_credits, - (unsigned long long)sconn->smb2.seqnum_low, - (unsigned int)sconn->smb2.seqnum_range)); + (unsigned int)xconn->smb2.credits.granted, + (unsigned int)xconn->smb2.credits.max, + (unsigned long long)xconn->smb2.credits.seq_low, + (unsigned int)xconn->smb2.credits.seq_range)); } static void smb2_calculate_credits(const struct smbd_smb2_request *inreq, @@ -1805,13 +1811,14 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req) NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req, uint32_t data_length) { + struct smbXsrv_connection *xconn = req->sconn->conn; uint16_t needed_charge; uint16_t credit_charge = 1; const uint8_t *inhdr; inhdr = SMBD_SMB2_IN_HDR_PTR(req); - if (req->sconn->smb2.supports_multicredit) { + if (xconn->smb2.credits.multicredit) { credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE); credit_charge = MAX(credit_charge, 1); } @@ -2970,7 +2977,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s return NT_STATUS_OK; } - max_send_queue_len = MAX(1, sconn->smb2.max_credits/16); + max_send_queue_len = MAX(1, xconn->smb2.credits.max/16); cur_send_queue_len = xconn->smb2.send_queue_len; if (cur_send_queue_len > max_send_queue_len) {