diff --git a/source3/include/proto.h b/source3/include/proto.h index 5a8eeb1e25a..b6bc7a2f75a 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6783,11 +6783,13 @@ int srv_set_message(char *buf, int num_words, int num_bytes, bool zero); -void remove_deferred_open_smb_message(uint16 mid); -void schedule_deferred_open_smb_message(uint16 mid); -bool open_was_deferred(uint16 mid); -struct pending_message_list *get_open_deferred_message(uint16 mid); -bool push_deferred_smb_message(struct smb_request *req, +void remove_deferred_open_message_smb(uint16_t mid); +void schedule_deferred_open_message_smb(uint16_t mid); +bool open_was_deferred(uint16_t mid); +bool get_deferred_open_message_state(uint16_t mid, + struct timeval *p_request_time, + void **pp_state); +bool push_deferred_open_message_smb(struct smb_request *req, struct timeval request_time, struct timeval timeout, char *private_data, size_t priv_len); diff --git a/source3/include/smb.h b/source3/include/smb.h index 48ab2f22833..853ced0aa60 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1978,4 +1978,7 @@ struct child_pid { pid_t pid; }; +/* Used to keep track of deferred opens. */ +struct deferred_open_record; + #endif /* _SMB_H */ diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index 378d9f69f75..eb22584772f 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -371,9 +371,9 @@ static void defer_open(struct share_mode_lock *lck, (unsigned int)request_time.tv_usec, (unsigned int)req->mid)); - if (!push_deferred_smb_message(req, request_time, timeout, + if (!push_deferred_open_message_smb(req, request_time, timeout, (char *)state, sizeof(*state))) { - exit_server("push_deferred_smb_message failed"); + exit_server("push_deferred_open_message_smb failed"); } add_deferred_open(lck, req->mid, request_time, state->id); } @@ -457,7 +457,6 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, mode_t unx_mode = (mode_t)0; int info; uint32 existing_dos_attributes = 0; - struct pending_message_list *pml = NULL; struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; @@ -542,39 +541,40 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * Only non-internal opens can be deferred at all */ - if ((req != NULL) - && ((pml = get_open_deferred_message(req->mid)) != NULL)) { - struct deferred_open_record *state = - (struct deferred_open_record *)pml->private_data.data; + if (req) { + void *ptr; + if (get_deferred_open_message_state(req->mid, + &request_time, + &ptr)) { + struct deferred_open_record *state = (struct deferred_open_record *)ptr; - /* Remember the absolute time of the original - request with this mid. We'll use it later to - see if this has timed out. */ + /* Remember the absolute time of the original + request with this mid. We'll use it later to + see if this has timed out. */ - request_time = pml->request_time; + /* Remove the deferred open entry under lock. */ + lck = get_share_mode_lock(talloc_tos(), state->id, + NULL, NULL, NULL); + if (lck == NULL) { + DEBUG(0, ("could not get share mode lock\n")); + } else { + del_deferred_open_entry(lck, req->mid); + TALLOC_FREE(lck); + } - /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL, - NULL); - if (lck == NULL) { - DEBUG(0, ("could not get share mode lock\n")); - } else { - del_deferred_open_entry(lck, req->mid); - TALLOC_FREE(lck); - } + /* Ensure we don't reprocess this message. */ + remove_deferred_open_message_smb(req->mid); - /* Ensure we don't reprocess this message. */ - remove_deferred_open_smb_message(req->mid); - - /* - * When receiving a semlock_async_failure message, the - * deferred open will be marked as "failed". Returning - * INTERNAL_ERROR. - */ - if (state->failed) { - DEBUG(0, ("onefs_open_file_ntcreate: " - "semlock_async_failure detected!\n")); - return NT_STATUS_INTERNAL_ERROR; + /* + * When receiving a semlock_async_failure message, the + * deferred open will be marked as "failed". Returning + * INTERNAL_ERROR. + */ + if (state->failed) { + DEBUG(0, ("onefs_open_file_ntcreate: " + "semlock_async_failure detected!\n")); + return NT_STATUS_INTERNAL_ERROR; + } } } diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2a0024c4934..90d2f313452 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -159,7 +159,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, NTSTATUS status; if (req->smb2req) { - return smb2_push_blocking_lock_request(br_lck, + return push_blocking_lock_request_smb2(br_lck, req, fsp, lock_timeout, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 27bc1cef19d..bf181f3bd06 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -173,7 +173,7 @@ static void notify_deferred_opens(struct share_mode_lock *lck) * the head of the queue and changing the wait time to * zero. */ - schedule_deferred_open_smb_message(e->op_mid); + schedule_deferred_open_message_smb(e->op_mid); } else { char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 5eea0ce311a..f08da7b9a33 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -319,9 +319,9 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req); NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req); NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req); -void send_smb2_break_message(files_struct *fsp, uint8_t level); -void schedule_deferred_open_smb2_message(uint16 mid); -bool smb2_push_blocking_lock_request( struct byte_range_lock *br_lck, +/* SMB1 -> SMB2 glue. */ +void send_break_message_smb2(files_struct *fsp, uint8_t level); +bool push_blocking_lock_request_smb2( struct byte_range_lock *br_lck, struct smb_request *req, files_struct *fsp, int lock_timeout, @@ -332,6 +332,17 @@ bool smb2_push_blocking_lock_request( struct byte_range_lock *br_lck, uint64_t offset, uint64_t count, uint32_t blocking_pid); +void remove_deferred_open_message_smb2(uint16_t mid); +void schedule_deferred_open_message_smb2(uint16_t mid); +bool open_was_deferred_smb2(uint16_t mid); +bool get_deferred_open_message_state_smb2(uint16_t mid, + struct timeval *p_request_time, + void **pp_state); +bool push_deferred_open_message_smb2(struct smb_request *req, + struct timeval request_time, + struct timeval timeout, + char *private_data, + size_t priv_len); struct smbd_smb2_request { struct smbd_smb2_request *prev, *next; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0834e6d3d39..1e98e883887 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,8 +25,8 @@ extern const struct generic_mapping file_generic_mapping; struct deferred_open_record { - bool delayed_for_oplocks; - struct file_id id; + bool delayed_for_oplocks; + struct file_id id; }; static NTSTATUS create_file_unixpath(connection_struct *conn, @@ -1082,9 +1082,9 @@ static void defer_open(struct share_mode_lock *lck, (unsigned int)request_time.tv_usec, (unsigned int)req->mid)); - if (!push_deferred_smb_message(req, request_time, timeout, + if (!push_deferred_open_message_smb(req, request_time, timeout, (char *)state, sizeof(*state))) { - exit_server("push_deferred_smb_message failed"); + exit_server("push_deferred_open_message_smb failed"); } add_deferred_open(lck, req->mid, request_time, state->id); } @@ -1477,7 +1477,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, mode_t unx_mode = (mode_t)0; int info; uint32 existing_dos_attributes = 0; - struct pending_message_list *pml = NULL; struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; @@ -1543,29 +1542,30 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, * Only non-internal opens can be deferred at all */ - if ((req != NULL) - && ((pml = get_open_deferred_message(req->mid)) != NULL)) { - struct deferred_open_record *state = - (struct deferred_open_record *)pml->private_data.data; + if (req) { + void *ptr; + if (get_deferred_open_message_state(req->mid, + &request_time, + &ptr)) { - /* Remember the absolute time of the original - request with this mid. We'll use it later to - see if this has timed out. */ + struct deferred_open_record *state = (struct deferred_open_record *)ptr; + /* Remember the absolute time of the original + request with this mid. We'll use it later to + see if this has timed out. */ - request_time = pml->request_time; + /* Remove the deferred open entry under lock. */ + lck = get_share_mode_lock(talloc_tos(), state->id, + NULL, NULL, NULL); + if (lck == NULL) { + DEBUG(0, ("could not get share mode lock\n")); + } else { + del_deferred_open_entry(lck, req->mid); + TALLOC_FREE(lck); + } - /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL, - NULL); - if (lck == NULL) { - DEBUG(0, ("could not get share mode lock\n")); - } else { - del_deferred_open_entry(lck, req->mid); - TALLOC_FREE(lck); + /* Ensure we don't reprocess this message. */ + remove_deferred_open_message_smb(req->mid); } - - /* Ensure we don't reprocess this message. */ - remove_deferred_open_smb_message(req->mid); } status = check_name(conn, smb_fname->base_name); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e876e8c2868..c7cce4afadb 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -214,7 +214,7 @@ bool should_notify_deferred_opens() Set up an oplock break message. ****************************************************************************/ -static char *new_break_smb1_message(TALLOC_CTX *mem_ctx, +static char *new_break_message_smb1(TALLOC_CTX *mem_ctx, files_struct *fsp, uint8 cmd) { char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); @@ -354,9 +354,9 @@ static void add_oplock_timeout_handler(files_struct *fsp) } } -static void send_smb1_break_message(files_struct *fsp, uint8_t level) +static void send_break_message_smb1(files_struct *fsp, uint8_t level) { - char *break_msg = new_break_smb1_message(talloc_tos(), + char *break_msg = new_break_message_smb1(talloc_tos(), fsp, level); if (break_msg == NULL) { @@ -368,7 +368,7 @@ static void send_smb1_break_message(files_struct *fsp, uint8_t level) break_msg, false, 0, IS_CONN_ENCRYPTED(fsp->conn), NULL)) { - exit_server_cleanly("send_smb1_break_message: " + exit_server_cleanly("send_break_message_smb1: " "srv_send_smb failed."); } @@ -404,9 +404,9 @@ void break_level2_to_none_async(files_struct *fsp) /* Now send a break to none message to our client. */ if (sconn->allow_smb2) { - send_smb2_break_message(fsp, OPLOCKLEVEL_NONE); + send_break_message_smb2(fsp, OPLOCKLEVEL_NONE); } else { - send_smb1_break_message(fsp, OPLOCKLEVEL_NONE); + send_break_message_smb1(fsp, OPLOCKLEVEL_NONE); } /* Async level2 request, don't send a reply, just remove the oplock. */ @@ -543,10 +543,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, } if (sconn->allow_smb2) { - send_smb2_break_message(fsp, break_to_level2 ? + send_break_message_smb2(fsp, break_to_level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); } else { - send_smb1_break_message(fsp, break_to_level2 ? + send_break_message_smb1(fsp, break_to_level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); } @@ -609,9 +609,9 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, } if (sconn->allow_smb2) { - send_smb2_break_message(fsp, OPLOCKLEVEL_NONE); + send_break_message_smb2(fsp, OPLOCKLEVEL_NONE); } else { - send_smb1_break_message(fsp, OPLOCKLEVEL_NONE); + send_break_message_smb1(fsp, OPLOCKLEVEL_NONE); } fsp->sent_oplock_break = BREAK_TO_NONE_SENT; @@ -680,7 +680,7 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), msg.share_file_id, (unsigned int)msg.op_mid)); - schedule_deferred_open_smb_message(msg.op_mid); + schedule_deferred_open_message_smb(msg.op_mid); } static void process_open_retry_message(struct messaging_context *msg_ctx, @@ -708,7 +708,7 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id), (unsigned int)msg.op_mid)); - schedule_deferred_open_smb_message(msg.op_mid); + schedule_deferred_open_message_smb(msg.op_mid); } /**************************************************************************** diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index c80925ced31..754ba73bfdc 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -440,7 +440,6 @@ static void semlock_available_handler(uint64_t id) static void semlock_async_failure_handler(uint64_t id) { struct onefs_callback_record *cb; - struct pending_message_list *pml; struct deferred_open_record *state; DEBUG(1, ("semlock_async_failure_handler called: %llu\n", id)); @@ -465,13 +464,12 @@ static void semlock_async_failure_handler(uint64_t id) } /* Find the actual deferred open record. */ - if (!(pml = get_open_deferred_message(cb->data.mid))) { + if (!get_open_deferred_message_state(cb->data.mid, NULL, &state)) { DEBUG(0, ("Could not find deferred request for " "mid %d\n", cb->data.mid)); destroy_onefs_callback_record(id); return; } - state = (struct deferred_open_record *)pml->private_data.data; /* Update to failed so the client can be notified on retried open. */ state->failed = true; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ddafdff3a2e..1a000f1f08b 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -39,6 +39,7 @@ extern bool global_machine_password_needs_changing; static void construct_reply_common(struct smb_request *req, const char *inbuf, char *outbuf); +static struct pending_message_list *get_deferred_open_message_smb(uint16_t mid); static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn) { @@ -528,9 +529,9 @@ static void smbd_deferred_open_timer(struct event_context *ev, msg->seqnum, msg->encrypted, &msg->pcd); /* If it's still there and was processed, remove it. */ - msg = get_open_deferred_message(mid); + msg = get_deferred_open_message_smb(mid); if (msg && msg->processed) { - remove_deferred_open_smb_message(mid); + remove_deferred_open_message_smb(mid); } } @@ -600,13 +601,18 @@ static bool push_queued_message(struct smb_request *req, Function to delete a sharing violation open message by mid. ****************************************************************************/ -void remove_deferred_open_smb_message(uint16 mid) +void remove_deferred_open_message_smb(uint16_t mid) { struct pending_message_list *pml; + if (smbd_server_conn->allow_smb2) { + remove_deferred_open_message_smb2(mid); + return; + } + for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_deferred_open_smb_message: " + DEBUG(10,("remove_deferred_open_message_smb: " "deleting mid %u len %u\n", (unsigned int)mid, (unsigned int)pml->buf.length )); @@ -622,21 +628,20 @@ void remove_deferred_open_smb_message(uint16 mid) schedule it for immediate processing. ****************************************************************************/ -void schedule_deferred_open_smb_message(uint16 mid) +void schedule_deferred_open_message_smb(uint16_t mid) { - struct smbd_server_connection *sconn = smbd_server_conn; struct pending_message_list *pml; int i = 0; - if (sconn->allow_smb2) { - schedule_deferred_open_smb2_message(mid); + if (smbd_server_conn->allow_smb2) { + schedule_deferred_open_message_smb2(mid); return; } for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, + DEBUG(10,("schedule_deferred_open_message_smb: [%d] msg_mid = %u\n", i++, (unsigned int)msg_mid )); if (mid == msg_mid) { @@ -645,13 +650,13 @@ void schedule_deferred_open_smb_message(uint16 mid) if (pml->processed) { /* A processed message should not be * rescheduled. */ - DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR " + DEBUG(0,("schedule_deferred_open_message_smb: LOGIC ERROR " "message mid %u was already processed\n", msg_mid )); continue; } - DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", + DEBUG(10,("schedule_deferred_open_message_smb: scheduling mid %u\n", mid )); te = event_add_timed(smbd_event_context(), @@ -660,7 +665,7 @@ void schedule_deferred_open_smb_message(uint16 mid) smbd_deferred_open_timer, pml); if (!te) { - DEBUG(10,("schedule_deferred_open_smb_message: " + DEBUG(10,("schedule_deferred_open_message_smb: " "event_add_timed() failed, skipping mid %u\n", mid )); } @@ -672,7 +677,7 @@ void schedule_deferred_open_smb_message(uint16 mid) } } - DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", + DEBUG(10,("schedule_deferred_open_message_smb: failed to find message mid %u\n", mid )); } @@ -680,10 +685,14 @@ void schedule_deferred_open_smb_message(uint16 mid) Return true if this mid is on the deferred queue and was not yet processed. ****************************************************************************/ -bool open_was_deferred(uint16 mid) +bool open_was_deferred(uint16_t mid) { struct pending_message_list *pml; + if (smbd_server_conn->allow_smb2) { + return open_was_deferred_smb2(mid); + } + for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) { return True; @@ -696,7 +705,7 @@ bool open_was_deferred(uint16 mid) Return the message queued by this mid. ****************************************************************************/ -struct pending_message_list *get_open_deferred_message(uint16 mid) +static struct pending_message_list *get_deferred_open_message_smb(uint16_t mid) { struct pending_message_list *pml; @@ -708,29 +717,66 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) return NULL; } +/**************************************************************************** + Get the state data queued by this mid. +****************************************************************************/ + +bool get_deferred_open_message_state(uint16_t mid, + struct timeval *p_request_time, + void **pp_state) +{ + struct pending_message_list *pml; + + if (smbd_server_conn->allow_smb2) { + return get_deferred_open_message_state_smb2(mid, + p_request_time, + pp_state); + } + + pml = get_deferred_open_message_smb(mid); + if (!pml) { + return false; + } + if (p_request_time) { + *p_request_time = pml->request_time; + } + if (pp_state) { + *pp_state = (void *)pml->private_data.data; + } + return true; +} + /**************************************************************************** Function to push a deferred open smb message onto a linked list of local smb messages ready for processing. ****************************************************************************/ -bool push_deferred_smb_message(struct smb_request *req, +bool push_deferred_open_message_smb(struct smb_request *req, struct timeval request_time, struct timeval timeout, char *private_data, size_t priv_len) { struct timeval end_time; + if (req->smb2req) { + return push_deferred_open_message_smb2(req, + request_time, + timeout, + private_data, + priv_len); + } + if (req->unread_bytes) { - DEBUG(0,("push_deferred_smb_message: logic error ! " + DEBUG(0,("push_deferred_open_message_smb: logic error ! " "unread_bytes = %u\n", (unsigned int)req->unread_bytes )); - smb_panic("push_deferred_smb_message: " + smb_panic("push_deferred_open_message_smb: " "logic error unread_bytes != 0" ); } end_time = timeval_sum(&request_time, &timeout); - DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " + DEBUG(10,("push_deferred_open_message_smb: pushing message len %u mid %u " "timeout time [%u.%06u]\n", (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid, (unsigned int)end_time.tv_sec, diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 5057fc1fc13..8bb1bfc27ac 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -209,11 +209,6 @@ static NTSTATUS smbd_smb2_oplock_break_recv(struct tevent_req *req, return NT_STATUS_OK; } -void send_smb2_break_message(files_struct *fsp, uint8_t level) +void send_break_message_smb2(files_struct *fsp, uint8_t level) { } - -void schedule_deferred_open_smb2_message(uint16 mid) -{ - /* FIXME - mid needs to be uint64_t. */ -} diff --git a/source3/smbd/smb2_glue.c b/source3/smbd/smb2_glue.c index 3ecc790bba4..ac31ce54f03 100644 --- a/source3/smbd/smb2_glue.c +++ b/source3/smbd/smb2_glue.c @@ -64,3 +64,35 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req) return smbreq; } + +/* Dummy functions for the SMB1 -> SMB2 deferred open message + * hooks. */ + +void remove_deferred_open_message_smb2(uint16_t mid) +{ +} + +void schedule_deferred_open_message_smb2(uint16_t mid) +{ +} + +bool open_was_deferred_smb2(uint16_t mid) +{ + return false; +} + +bool get_deferred_open_message_state_smb2(uint16_t mid, + struct timeval *p_request_time, + void **pp_state) +{ + return false; +} + +bool push_deferred_open_message_smb2(struct smb_request *req, + struct timeval request_time, + struct timeval timeout, + char *private_data, + size_t priv_len) +{ + return false; +} diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 129bb2f330a..597034c1da0 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -387,7 +387,7 @@ static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req) * requests. */ -bool smb2_push_blocking_lock_request( struct byte_range_lock *br_lck, +bool push_blocking_lock_request_smb2( struct byte_range_lock *br_lck, struct smb_request *req, files_struct *fsp, int lock_timeout,