From d3cfcc04cfedbcbc36fc8b6294edfdcacb1cf2a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:21:57 +0200 Subject: [PATCH 01/20] s3:smb2_server: fix invalid TALLOC_FREE(iov) in smbd_smb2_inbuf_parse_compound() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_server.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 4a7abcb..d3a38e2 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -327,6 +327,11 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, uint8_t *body = NULL; uint32_t dyn_size; uint8_t *dyn = NULL; + struct iovec *iov_alloc = NULL; + + if (iov != req->in._vector) { + iov_alloc = iov; + } if (verified_buflen > taken) { len = verified_buflen - taken; @@ -388,7 +393,7 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, DEBUG(1, ("invalid session[%llu] in " "SMB2_TRANSFORM header\n", (unsigned long long)uid)); - TALLOC_FREE(iov); + TALLOC_FREE(iov_alloc); return NT_STATUS_USER_SESSION_DELETED; } @@ -401,7 +406,7 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, conn->protocol, tf_iov, 2); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(iov); + TALLOC_FREE(iov_alloc); return status; } @@ -459,11 +464,6 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, if (num_iov >= ARRAY_SIZE(req->in._vector)) { struct iovec *iov_tmp = NULL; - struct iovec *iov_alloc = NULL; - - if (iov != req->in._vector) { - iov_alloc = iov; - } iov_tmp = talloc_realloc(mem_ctx, iov_alloc, struct iovec, -- 1.7.9.5 From fa682920c7e86761c3fd6a17c27055628b87aabf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:30:21 +0200 Subject: [PATCH 02/20] s3:smb2_server: call smbd_smb2_flush_send_queue() directly This avoids recursion into smbd_smb2_io_handler(), which avoids confusion when analysing out put of performance analysing tools, e.g. callgrind. Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_server.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index d3a38e2..69fe9e4 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -34,8 +34,7 @@ static void smbd_smb2_connection_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data); -static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, - uint16_t fde_flags); +static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn); static const struct smbd_smb2_dispatch_table { uint16_t opcode; @@ -1265,7 +1264,7 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL); nreq->sconn->smb2.send_queue_len++; - status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE); + status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1598,7 +1597,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL); sconn->smb2.send_queue_len++; - status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE); + status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(sconn, nt_errstr(status)); @@ -2499,7 +2498,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL); req->sconn->smb2.send_queue_len++; - status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE); + status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2829,7 +2828,7 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL); state->sconn->smb2.send_queue_len++; - status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE); + status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { return status; } -- 1.7.9.5 From c155737e1411f3f1f24911b7bcf0acd6a3f284c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:37:14 +0200 Subject: [PATCH 03/20] s3:smbd: avoid using client_get_tcp_info() We already have the required information as stack variable in the current function. There's no need to call get[peer|sock]name() twice. Signed-off-by: Stefan Metzmacher --- source3/smbd/process.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8a1d1d6..2003bfb 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3389,8 +3389,12 @@ void smbd_process(struct tevent_context *ev_ctx, TALLOC_CTX *frame = talloc_stackframe(); struct smbXsrv_connection *conn; struct smbd_server_connection *sconn; - struct sockaddr_storage ss; - struct sockaddr *sa = NULL; + struct sockaddr_storage ss_srv; + void *sp_srv = (void *)&ss_srv; + struct sockaddr *sa_srv = (struct sockaddr *)sp_srv; + struct sockaddr_storage ss_clnt; + void *sp_clnt = (void *)&ss_clnt; + struct sockaddr *sa_clnt = (struct sockaddr *)sp_clnt; socklen_t sa_socklen; struct tsocket_address *local_address = NULL; struct tsocket_address *remote_address = NULL; @@ -3458,16 +3462,15 @@ void smbd_process(struct tevent_context *ev_ctx, set_socket_options(sconn->sock, "SO_KEEPALIVE"); set_socket_options(sconn->sock, lp_socket_options()); - sa = (struct sockaddr *)(void *)&ss; - sa_socklen = sizeof(ss); - ret = getpeername(sconn->sock, sa, &sa_socklen); + sa_socklen = sizeof(ss_clnt); + ret = getpeername(sock_fd, sa_clnt, &sa_socklen); if (ret != 0) { int level = (errno == ENOTCONN)?2:0; DEBUG(level,("getpeername() failed - %s\n", strerror(errno))); exit_server_cleanly("getpeername() failed.\n"); } ret = tsocket_address_bsd_from_sockaddr(sconn, - sa, sa_socklen, + sa_clnt, sa_socklen, &remote_address); if (ret != 0) { DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n", @@ -3475,16 +3478,15 @@ void smbd_process(struct tevent_context *ev_ctx, exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n"); } - sa = (struct sockaddr *)(void *)&ss; - sa_socklen = sizeof(ss); - ret = getsockname(sconn->sock, sa, &sa_socklen); + sa_socklen = sizeof(ss_srv); + ret = getsockname(sock_fd, sa_srv, &sa_socklen); if (ret != 0) { int level = (errno == ENOTCONN)?2:0; DEBUG(level,("getsockname() failed - %s\n", strerror(errno))); exit_server_cleanly("getsockname() failed.\n"); } ret = tsocket_address_bsd_from_sockaddr(sconn, - sa, sa_socklen, + sa_srv, sa_socklen, &local_address); if (ret != 0) { DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n", @@ -3670,22 +3672,12 @@ void smbd_process(struct tevent_context *ev_ctx, * tickle acks, triggering a reconnection by the * client. */ + NTSTATUS status; - struct sockaddr_storage srv, clnt; - - if (client_get_tcp_info(sconn->sock, &srv, &clnt) == 0) { - NTSTATUS status; - status = smbd_register_ips(sconn, &srv, &clnt); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("ctdbd_register_ips failed: %s\n", - nt_errstr(status))); - } - } else { - int level = (errno == ENOTCONN)?2:0; - DEBUG(level,("Unable to get tcp info for " - "smbd_register_ips: %s\n", - strerror(errno))); - exit_server_cleanly("client_get_tcp_info() failed.\n"); + status = smbd_register_ips(sconn, &ss_srv, &ss_clnt); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("ctdbd_register_ips failed: %s\n", + nt_errstr(status))); } } -- 1.7.9.5 From 911a194a3ae2e95393b87baa979949e721855c85 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:40:31 +0200 Subject: [PATCH 04/20] s3:smbd: remove unused client_get_tcp_info() Signed-off-by: Stefan Metzmacher --- source3/smbd/process.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2003bfb..cd748c0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2611,21 +2611,6 @@ static NTSTATUS smbd_register_ips(struct smbd_server_connection *sconn, return ctdbd_register_ips(cconn, srv, clnt, release_ip, state); } -static int client_get_tcp_info(int sock, struct sockaddr_storage *server, - struct sockaddr_storage *client) -{ - socklen_t length; - length = sizeof(*server); - if (getsockname(sock, (struct sockaddr *)server, &length) != 0) { - return -1; - } - length = sizeof(*client); - if (getpeername(sock, (struct sockaddr *)client, &length) != 0) { - return -1; - } - return 0; -} - static void msg_kill_client_ip(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) -- 1.7.9.5 From ab82a9a0dee006fce7193ba267bfc05824a38c39 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:59:43 +0200 Subject: [PATCH 05/20] s3:smbd: avoid get_peer_addr() and use tsocket_address_string() There's no need to do syscalls, if we already have the information in userspace. Signed-off-by: Stefan Metzmacher --- source3/smbd/process.c | 19 ++++++++++++------- source3/smbd/reply.c | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cd748c0..ed2e776 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -148,6 +148,7 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, bool do_encrypt, struct smb_perfcount_data *pcd) { + struct smbXsrv_connection *xconn = sconn->conn; size_t len = 0; ssize_t ret; char *buf_out = buffer; @@ -181,15 +182,16 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, ret = write_data(sconn->sock, buf_out, len); if (ret <= 0) { - - char addr[INET6_ADDRSTRLEN]; + int saved_errno = errno; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); + errno = saved_errno; /* * Try and give an error message saying what * client failed. */ DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n", - (int)getpid(), (int)len, - get_peer_addr(sconn->sock, addr, sizeof(addr)), + (int)getpid(), (int)len, addr, (int)ret, strerror(errno) )); srv_free_enc_buffer(sconn, buf_out); @@ -2644,6 +2646,7 @@ static bool keepalive_fn(const struct timeval *now, void *private_data) { struct smbd_server_connection *sconn = talloc_get_type_abort( private_data, struct smbd_server_connection); + struct smbXsrv_connection *xconn = sconn->conn; bool ret; if (sconn->using_smb2) { @@ -2656,15 +2659,17 @@ static bool keepalive_fn(const struct timeval *now, void *private_data) smbd_unlock_socket(sconn); if (!ret) { - char addr[INET6_ADDRSTRLEN]; + int saved_errno = errno; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); + errno = saved_errno; /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("send_keepalive failed for client %s. " "Error %s - exiting\n", - get_peer_addr(sconn->sock, addr, sizeof(addr)), - strerror(errno))); + addr, strerror(errno))); return False; } return True; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f737d74..c97196e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3156,21 +3156,23 @@ void sendfile_short_send(files_struct *fsp, static void reply_readbraw_error(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; char header[4]; SIVAL(header,0,0); smbd_lock_socket(sconn); if (write_data(sconn->sock,header,4) != 4) { - char addr[INET6_ADDRSTRLEN]; + int saved_errno = errno; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("write_data failed for client %s. " - "Error %s\n", - get_peer_addr(sconn->sock, addr, sizeof(addr)), - strerror(errno))); + "Error %s\n", addr, strerror(saved_errno))); + errno = saved_errno; fail_readraw(); } @@ -3189,6 +3191,7 @@ static void send_file_readbraw(connection_struct *conn, ssize_t mincount) { struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; char *outbuf = NULL; ssize_t ret=0; @@ -3288,16 +3291,16 @@ normal_readbraw: _smb_setlen(outbuf,ret); if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) { - char addr[INET6_ADDRSTRLEN]; + int saved_errno = errno; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("write_data failed for client %s. " - "Error %s\n", - get_peer_addr(fsp->conn->sconn->sock, addr, - sizeof(addr)), - strerror(errno))); + "Error %s\n", addr, strerror(saved_errno))); + errno = saved_errno; fail_readraw(); } @@ -3691,6 +3694,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, files_struct *fsp, off_t startpos, size_t smb_maxcnt) { + struct smbXsrv_connection *xconn = req->sconn->conn; ssize_t nread = -1; struct lock_struct lock; int saved_errno = 0; @@ -3814,24 +3818,25 @@ normal_read: if ((smb_maxcnt & 0xFF0000) > 0x10000) { uint8 headerbuf[smb_size + 2*12]; + ssize_t ret; construct_reply_common_req(req, (char *)headerbuf); setup_readX_header(req, (char *)headerbuf, smb_maxcnt); /* Send out the header. */ - if (write_data(req->sconn->sock, (char *)headerbuf, - sizeof(headerbuf)) != sizeof(headerbuf)) { - - char addr[INET6_ADDRSTRLEN]; + ret = write_data(req->sconn->sock, (char *)headerbuf, + sizeof(headerbuf)); + saved_errno = errno; + if (ret != sizeof(headerbuf)) { + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("write_data failed for client %s. " - "Error %s\n", - get_peer_addr(req->sconn->sock, addr, - sizeof(addr)), - strerror(errno))); + "Error %s\n", addr, strerror(saved_errno))); + errno = saved_errno; DEBUG(0,("send_file_readX: write_data failed for file " "%s (%s). Terminating\n", fsp_str_dbg(fsp), @@ -4104,6 +4109,7 @@ static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout, void reply_writebraw(struct smb_request *req) { connection_struct *conn = req->conn; + struct smbXsrv_connection *xconn = req->sconn->conn; char *buf = NULL; ssize_t nwritten=0; ssize_t total_written=0; @@ -4267,14 +4273,13 @@ void reply_writebraw(struct smb_request *req) status = read_data(req->sconn->sock, buf+4, numtowrite); if (!NT_STATUS_IS_OK(status)) { - char addr[INET6_ADDRSTRLEN]; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); /* Try and give an error message * saying what client failed. */ DEBUG(0, ("reply_writebraw: Oversize secondary write " "raw read failed (%s) for client %s. " - "Terminating\n", nt_errstr(status), - get_peer_addr(req->sconn->sock, addr, - sizeof(addr)))); + "Terminating\n", nt_errstr(status), addr)); exit_server_cleanly("secondary writebraw failed"); } -- 1.7.9.5 From 28fbb585fcf8f4de25684af19e112fbfcb4d9bcb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 May 2014 19:59:12 +0200 Subject: [PATCH 06/20] s3:smbd: move sconn->nbt.* to xconn->transport.nbt.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 9 ++++++--- source3/smbd/process.c | 2 -- source3/smbd/reply.c | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index cd99fe7..d2aae9f 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -338,6 +338,12 @@ struct smbXsrv_connection { struct { struct { + bool got_session; + } nbt; + } transport; + + struct { + struct { uint32_t capabilities; struct GUID guid; uint16_t security_mode; @@ -649,9 +655,6 @@ struct smbd_server_connection { struct messaging_context *msg_ctx; struct sys_notify_context *sys_notify_ctx; struct notify_context *notify_ctx; - struct { - bool got_session; - } nbt; bool using_smb2; int trans_num; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ed2e776..fc5bd43 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3671,8 +3671,6 @@ void smbd_process(struct tevent_context *ev_ctx, } } - sconn->nbt.got_session = false; - tmp = lp_max_xmit(); tmp = MAX(tmp, SMB_BUFFER_SIZE_MIN); tmp = MIN(tmp, SMB_BUFFER_SIZE_MAX); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index c97196e..0c52ed6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -533,6 +533,7 @@ static void reply_called_name_not_present(char *outbuf) void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size) { + struct smbXsrv_connection *xconn = sconn->conn; int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); /* @@ -556,7 +557,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb *name1 = *name2 = 0; - if (sconn->nbt.got_session) { + if (xconn->transport.nbt.got_session) { exit_server_cleanly("multiple session request not permitted"); } @@ -642,7 +643,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inb reload_services(sconn, conn_snum_used, true); reopen_logs(); - sconn->nbt.got_session = true; + xconn->transport.nbt.got_session = true; break; } -- 1.7.9.5 From f90c7fbd351be8776743e61e4e9dd63cae7b9a09 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 May 2014 23:23:34 +0200 Subject: [PATCH 07/20] s3:smbd: move sconn->sock to xconn->transport.sock This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 3 ++- source3/smbd/msdfs.c | 1 - source3/smbd/process.c | 41 ++++++++++++++++++------------- source3/smbd/reply.c | 55 +++++++++++++++++++++++------------------- source3/smbd/server_reload.c | 11 ++++++--- source3/smbd/smb2_read.c | 3 ++- source3/smbd/smb2_server.c | 15 ++++++++---- source3/smbd/vfs.c | 4 +-- 8 files changed, 78 insertions(+), 55 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index d2aae9f..3be70a5 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -337,6 +337,8 @@ struct smbXsrv_connection { enum protocol_types protocol; struct { + int sock; + struct { bool got_session; } nbt; @@ -647,7 +649,6 @@ struct user_struct { struct smbd_server_connection { NTSTATUS status; - int sock; const struct tsocket_address *local_address; const struct tsocket_address *remote_address; const char *remote_hostname; diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 97849d2..6cf506c 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -246,7 +246,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx, sconn->ev_ctx = ev; sconn->msg_ctx = msg; - sconn->sock = -1; sconn->smb1.echo_handler.trusted_fd = -1; sconn->smb1.echo_handler.socket_lock_fd = -1; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fc5bd43..7762c7f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -180,7 +180,7 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, len = smb_len_large(buf_out) + 4; - ret = write_data(sconn->sock, buf_out, len); + ret = write_data(xconn->transport.sock, buf_out, len); if (ret <= 0) { int saved_errno = errno; char *addr = tsocket_address_string(xconn->remote_address, @@ -2384,6 +2384,7 @@ static void smbd_server_connection_write_handler( static void smbd_server_connection_read_handler( struct smbd_server_connection *sconn, int fd) { + struct smbXsrv_connection *xconn = sconn->conn; uint8_t *inbuf = NULL; size_t inbuf_len = 0; size_t unread_bytes = 0; @@ -2406,7 +2407,7 @@ static void smbd_server_connection_read_handler( } } - from_client = (sconn->sock == fd); + from_client = (xconn->transport.sock == fd); if (async_echo && from_client) { smbd_lock_socket(sconn); @@ -2453,6 +2454,7 @@ static void smbd_server_connection_handler(struct tevent_context *ev, { struct smbd_server_connection *conn = talloc_get_type(private_data, struct smbd_server_connection); + struct smbXsrv_connection *xconn = conn->conn; if (!NT_STATUS_IS_OK(conn->status)) { /* @@ -2468,7 +2470,7 @@ static void smbd_server_connection_handler(struct tevent_context *ev, return; } if (flags & TEVENT_FD_READ) { - smbd_server_connection_read_handler(conn, conn->sock); + smbd_server_connection_read_handler(conn, xconn->transport.sock); return; } } @@ -2655,7 +2657,7 @@ static bool keepalive_fn(const struct timeval *now, void *private_data) } smbd_lock_socket(sconn); - ret = send_keepalive(sconn->sock); + ret = send_keepalive(xconn->transport.sock); smbd_unlock_socket(sconn); if (!ret) { @@ -2745,6 +2747,7 @@ static struct tevent_req *smbd_echo_read_send( { struct tevent_req *req, *subreq; struct smbd_echo_read_state *state; + struct smbXsrv_connection *xconn = sconn->conn; req = tevent_req_create(mem_ctx, &state, struct smbd_echo_read_state); @@ -2754,7 +2757,7 @@ static struct tevent_req *smbd_echo_read_send( state->ev = ev; state->sconn = sconn; - subreq = wait_for_read_send(state, ev, sconn->sock); + subreq = wait_for_read_send(state, ev, xconn->transport.sock); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -2797,6 +2800,7 @@ static void smbd_echo_read_waited(struct tevent_req *subreq) struct smbd_echo_read_state *state = tevent_req_data( req, struct smbd_echo_read_state); struct smbd_server_connection *sconn = state->sconn; + struct smbXsrv_connection *xconn = sconn->conn; bool ok; NTSTATUS status; size_t unread = 0; @@ -2816,7 +2820,7 @@ static void smbd_echo_read_waited(struct tevent_req *subreq) return; } - if (!fd_is_readable(sconn->sock)) { + if (!fd_is_readable(xconn->transport.sock)) { DEBUG(10,("echo_handler[%d] the parent smbd was faster\n", (int)getpid())); @@ -2828,7 +2832,8 @@ static void smbd_echo_read_waited(struct tevent_req *subreq) return; } - subreq = wait_for_read_send(state, state->ev, sconn->sock); + subreq = wait_for_read_send(state, state->ev, + xconn->transport.sock); if (tevent_req_nomem(subreq, req)) { return; } @@ -2836,7 +2841,9 @@ static void smbd_echo_read_waited(struct tevent_req *subreq) return; } - status = receive_smb_talloc(state, sconn, sconn->sock, &state->buf, + status = receive_smb_talloc(state, sconn, + xconn->transport.sock, + &state->buf, 0 /* timeout */, &unread, &encrypted, @@ -3402,6 +3409,7 @@ void smbd_process(struct tevent_context *ev_ctx, conn->ev_ctx = ev_ctx; conn->msg_ctx = msg_ctx; + conn->transport.sock = sock_fd; sconn = talloc_zero(conn, struct smbd_server_connection); if (!sconn) { @@ -3418,7 +3426,6 @@ void smbd_process(struct tevent_context *ev_ctx, sconn->ev_ctx = ev_ctx; sconn->msg_ctx = msg_ctx; - sconn->sock = sock_fd; sconn->smb1.echo_handler.trusted_fd = -1; sconn->smb1.echo_handler.socket_lock_fd = -1; @@ -3447,10 +3454,10 @@ void smbd_process(struct tevent_context *ev_ctx, } /* Ensure child is set to blocking mode */ - set_blocking(sconn->sock,True); + set_blocking(sock_fd,True); - set_socket_options(sconn->sock, "SO_KEEPALIVE"); - set_socket_options(sconn->sock, lp_socket_options()); + set_socket_options(sock_fd, "SO_KEEPALIVE"); + set_socket_options(sock_fd, lp_socket_options()); sa_socklen = sizeof(ss_clnt); ret = getpeername(sock_fd, sa_clnt, &sa_socklen); @@ -3685,11 +3692,11 @@ void smbd_process(struct tevent_context *ev_ctx, } sconn->smb1.fde = tevent_add_fd(ev_ctx, - sconn, - sconn->sock, - TEVENT_FD_READ, - smbd_server_connection_handler, - sconn); + sconn, + sock_fd, + TEVENT_FD_READ, + smbd_server_connection_handler, + sconn); if (!sconn->smb1.fde) { exit_server("failed to create smbd_server_connection fde"); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0c52ed6..67c0f81 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -431,6 +431,7 @@ bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req, static bool netbios_session_retarget(struct smbd_server_connection *sconn, const char *name, int name_type) { + struct smbXsrv_connection *xconn = sconn->conn; char *trim_name; char *trim_name_type; const char *retarget_parm; @@ -443,7 +444,7 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn, bool ret = false; uint8_t outbuf[10]; - if (get_socket_port(sconn->sock) != NBT_SMB_PORT) { + if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) { return false; } @@ -3024,6 +3025,7 @@ static void fail_readraw(void) ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread) { + struct smbXsrv_connection *xconn = fsp->conn->sconn->conn; size_t bufsize; size_t tosend = nread; char *buf; @@ -3058,19 +3060,19 @@ ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread) memset(buf + ret, '\0', cur_read - ret); } - if (write_data(fsp->conn->sconn->sock, buf, cur_read) - != cur_read) { - char addr[INET6_ADDRSTRLEN]; + ret = write_data(xconn->transport.sock, buf, cur_read); + if (ret != cur_read) { + int saved_errno = errno; + char *addr = tsocket_address_string(xconn->remote_address, + talloc_tos()); /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("write_data failed for client %s. " - "Error %s\n", - get_peer_addr(fsp->conn->sconn->sock, addr, - sizeof(addr)), - strerror(errno))); + "Error %s\n", addr, strerror(saved_errno))); SAFE_FREE(buf); + errno = saved_errno; return -1; } tosend -= cur_read; @@ -3091,6 +3093,8 @@ void sendfile_short_send(files_struct *fsp, size_t headersize, size_t smb_maxcnt) { + struct smbXsrv_connection *xconn = fsp->conn->sconn->conn; + #define SHORT_SEND_BUFSIZE 1024 if (nread < headersize) { DEBUG(0,("sendfile_short_send: sendfile failed to send " @@ -3127,21 +3131,21 @@ void sendfile_short_send(files_struct *fsp, * about efficiency here :-) */ size_t to_write; + ssize_t ret; to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread); - if (write_data(fsp->conn->sconn->sock, buf, to_write) - != to_write) { - char addr[INET6_ADDRSTRLEN]; + ret = write_data(xconn->transport.sock, buf, to_write); + if (ret != to_write) { + int saved_errno = errno; + char *addr = tsocket_address_string( + xconn->remote_address, + talloc_tos()); /* * Try and give an error message saying what * client failed. */ DEBUG(0, ("write_data failed for client %s. " - "Error %s\n", - get_peer_addr( - fsp->conn->sconn->sock, addr, - sizeof(addr)), - strerror(errno))); + "Error %s\n", addr, strerror(saved_errno))); exit_server_cleanly("sendfile_short_send: " "write_data failed"); } @@ -3163,7 +3167,7 @@ static void reply_readbraw_error(struct smbd_server_connection *sconn) SIVAL(header,0,0); smbd_lock_socket(sconn); - if (write_data(sconn->sock,header,4) != 4) { + if (write_data(xconn->transport.sock,header,4) != 4) { int saved_errno = errno; char *addr = tsocket_address_string(xconn->remote_address, talloc_tos()); @@ -3213,7 +3217,7 @@ static void send_file_readbraw(connection_struct *conn, _smb_setlen(header,nread); header_blob = data_blob_const(header, 4); - sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp, + sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header_blob, startpos, nread); if (sendfile_read == -1) { @@ -3291,7 +3295,7 @@ normal_readbraw: } _smb_setlen(outbuf,ret); - if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) { + if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) { int saved_errno = errno; char *addr = tsocket_address_string(xconn->remote_address, talloc_tos()); @@ -3749,7 +3753,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, construct_reply_common_req(req, (char *)headerbuf); setup_readX_header(req, (char *)headerbuf, smb_maxcnt); - nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header, + nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header, startpos, smb_maxcnt); if (nread == -1) { /* Returning ENOSYS means no data at all was sent. @@ -3825,7 +3829,7 @@ normal_read: setup_readX_header(req, (char *)headerbuf, smb_maxcnt); /* Send out the header. */ - ret = write_data(req->sconn->sock, (char *)headerbuf, + ret = write_data(xconn->transport.sock, (char *)headerbuf, sizeof(headerbuf)); saved_errno = errno; if (ret != sizeof(headerbuf)) { @@ -4247,7 +4251,7 @@ void reply_writebraw(struct smb_request *req) } /* Now read the raw data into the buffer and write it */ - status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT, + status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT, &numtowrite); if (!NT_STATUS_IS_OK(status)) { exit_server_cleanly("secondary writebraw failed"); @@ -4271,7 +4275,7 @@ void reply_writebraw(struct smb_request *req) (int)tcount,(int)nwritten,(int)numtowrite)); } - status = read_data(req->sconn->sock, buf+4, numtowrite); + status = read_data(xconn->transport.sock, buf+4, numtowrite); if (!NT_STATUS_IS_OK(status)) { char *addr = tsocket_address_string(xconn->remote_address, @@ -4335,7 +4339,7 @@ void reply_writebraw(struct smb_request *req) * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this. * JRA. */ - if (!send_keepalive(req->sconn->sock)) { + if (!send_keepalive(xconn->transport.sock)) { exit_server_cleanly("reply_writebraw: send of " "keepalive failed"); } @@ -4703,6 +4707,7 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn, void reply_write_and_X(struct smb_request *req) { connection_struct *conn = req->conn; + struct smbXsrv_connection *xconn = req->sconn->conn; files_struct *fsp; struct lock_struct lock; off_t startpos; @@ -4859,7 +4864,7 @@ void reply_write_and_X(struct smb_request *req) out: if (req->unread_bytes) { /* writeX failed. drain socket. */ - if (drain_socket(req->sconn->sock, req->unread_bytes) != + if (drain_socket(xconn->transport.sock, req->unread_bytes) != req->unread_bytes) { smb_panic("failed to drain pending bytes"); } diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c index e1e3f9a..627ad8b 100644 --- a/source3/smbd/server_reload.c +++ b/source3/smbd/server_reload.c @@ -139,8 +139,13 @@ bool reload_services(struct smbd_server_connection *sconn, bool (*snumused) (struct smbd_server_connection *, int), bool test) { + struct smbXsrv_connection *xconn = NULL; bool ret; + if (sconn != NULL) { + xconn = sconn->conn; + } + if (lp_loaded()) { char *fname = lp_next_configfile(talloc_tos()); if (file_exist(fname) && @@ -173,9 +178,9 @@ bool reload_services(struct smbd_server_connection *sconn, load_interfaces(); - if (sconn != NULL) { - set_socket_options(sconn->sock, "SO_KEEPALIVE"); - set_socket_options(sconn->sock, lp_socket_options()); + if (xconn != NULL) { + set_socket_options(xconn->transport.sock, "SO_KEEPALIVE"); + set_socket_options(xconn->transport.sock, lp_socket_options()); } mangle_reset_cache(); diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 05563b2..db8312b 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -184,9 +184,10 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state) uint32_t in_length = state->in_length; uint64_t in_offset = state->in_offset; files_struct *fsp = state->fsp; + struct smbXsrv_connection *xconn = fsp->conn->sconn->conn; ssize_t nread; - nread = SMB_VFS_SENDFILE(fsp->conn->sconn->sock, + nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, state->smb2req->queue_entry.sendfile_header, in_offset, diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 69fe9e4..d11e078 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -200,6 +200,8 @@ bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size) static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; + TALLOC_FREE(sconn->smb1.fde); sconn->smb2.send_queue = NULL; @@ -216,7 +218,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx, sconn, - sconn->sock, + xconn->transport.sock, TEVENT_FD_READ, smbd_smb2_connection_handler, sconn); @@ -225,7 +227,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) } /* Ensure child is set to non-blocking mode */ - set_blocking(sconn->sock, false); + set_blocking(xconn->transport.sock, false); return NT_STATUS_OK; } @@ -2646,6 +2648,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, DATA_BLOB *info, const char *location) { + struct smbXsrv_connection *xconn = req->sconn->conn; DATA_BLOB body; DATA_BLOB _dyn; uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req); @@ -2660,7 +2663,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, size_t ret; errno = 0; - ret = drain_socket(req->sconn->sock, unread_bytes); + ret = drain_socket(xconn->transport.sock, unread_bytes); if (ret != unread_bytes) { NTSTATUS error; @@ -3065,6 +3068,7 @@ static int socket_error_from_errno(int ret, static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; int ret; int err; bool retry; @@ -3117,7 +3121,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) continue; } - ret = writev(sconn->sock, e->vector, e->count); + ret = writev(xconn->transport.sock, e->vector, e->count); if (ret == 0) { /* propagate end of file */ return NT_STATUS_INTERNAL_ERROR; @@ -3175,6 +3179,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, uint16_t fde_flags) { + struct smbXsrv_connection *xconn = sconn->conn; struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state; struct smbd_smb2_request *req = NULL; size_t min_recvfile_size = UINT32_MAX; @@ -3217,7 +3222,7 @@ again: state->vector.iov_len = NBT_HDR_SIZE; } - ret = readv(sconn->sock, &state->vector, 1); + ret = readv(xconn->transport.sock, &state->vector, 1); if (ret == 0) { /* propagate end of file */ return NT_STATUS_END_OF_FILE; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 897bf1f3..023f02a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -428,7 +428,7 @@ ssize_t vfs_write_data(struct smb_request *req, ssize_t ret; if (req && req->unread_bytes) { - int sockfd = req->sconn->sock; + int sockfd = req->sconn->conn->transport.sock; int old_flags; SMB_ASSERT(req->unread_bytes == N); /* VFS_RECVFILE must drain the socket @@ -472,7 +472,7 @@ ssize_t vfs_pwrite_data(struct smb_request *req, ssize_t ret; if (req && req->unread_bytes) { - int sockfd = req->sconn->sock; + int sockfd = req->sconn->conn->transport.sock; SMB_ASSERT(req->unread_bytes == N); /* VFS_RECVFILE must drain the socket * before returning. */ -- 1.7.9.5 From eb684c970902a7252f62c6056c5056777908bd93 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 08:45:01 +0200 Subject: [PATCH 08/20] s3:smbd: move sconn->smb1.fde to xconn->transport.fde This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 3 +-- source3/smbd/process.c | 18 +++++++++--------- source3/smbd/smb2_server.c | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 3be70a5..eb85184 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -338,6 +338,7 @@ struct smbXsrv_connection { struct { int sock; + struct tevent_fd *fde; struct { bool got_session; @@ -691,8 +692,6 @@ struct smbd_server_connection { } oplocks; struct { - struct tevent_fd *fde; - struct { /* * fd for the fcntl lock mutexing access to our sock diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7762c7f..93993e0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2460,8 +2460,8 @@ static void smbd_server_connection_handler(struct tevent_context *ev, /* * we're not supposed to do any io */ - TEVENT_FD_NOT_READABLE(conn->smb1.fde); - TEVENT_FD_NOT_WRITEABLE(conn->smb1.fde); + TEVENT_FD_NOT_READABLE(xconn->transport.fde); + TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde); return; } @@ -3691,13 +3691,13 @@ void smbd_process(struct tevent_context *ev_ctx, exit_server("init_dptrs() failed"); } - sconn->smb1.fde = tevent_add_fd(ev_ctx, - sconn, - sock_fd, - TEVENT_FD_READ, - smbd_server_connection_handler, - sconn); - if (!sconn->smb1.fde) { + conn->transport.fde = tevent_add_fd(ev_ctx, + sconn, + sock_fd, + TEVENT_FD_READ, + smbd_server_connection_handler, + sconn); + if (!conn->transport.fde) { exit_server("failed to create smbd_server_connection fde"); } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index d11e078..7290d98 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -202,7 +202,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) { struct smbXsrv_connection *xconn = sconn->conn; - TALLOC_FREE(sconn->smb1.fde); + TALLOC_FREE(xconn->transport.fde); sconn->smb2.send_queue = NULL; -- 1.7.9.5 From d165fc45ce6c2c3440161845a2bbb7495782742c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 09:07:47 +0200 Subject: [PATCH 09/20] s3:smbd: move sconn->status to xconn->transport.status This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 2 +- source3/smbd/process.c | 15 +++++++++------ source3/smbd/server_exit.c | 6 +++--- source3/smbd/smb2_server.c | 5 +++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index eb85184..23ba8d52 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -337,6 +337,7 @@ struct smbXsrv_connection { enum protocol_types protocol; struct { + NTSTATUS status; int sock; struct tevent_fd *fde; @@ -649,7 +650,6 @@ struct user_struct { }; struct smbd_server_connection { - NTSTATUS status; const struct tsocket_address *local_address; const struct tsocket_address *remote_address; const char *remote_hostname; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 93993e0..aa496de 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -153,7 +153,7 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, ssize_t ret; char *buf_out = buffer; - if (!NT_STATUS_IS_OK(sconn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ @@ -2456,7 +2456,7 @@ static void smbd_server_connection_handler(struct tevent_context *ev, struct smbd_server_connection); struct smbXsrv_connection *xconn = conn->conn; - if (!NT_STATUS_IS_OK(conn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ @@ -2482,8 +2482,9 @@ static void smbd_server_echo_handler(struct tevent_context *ev, { struct smbd_server_connection *conn = talloc_get_type(private_data, struct smbd_server_connection); + struct smbXsrv_connection *xconn = conn->conn; - if (!NT_STATUS_IS_OK(conn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ @@ -2516,8 +2517,9 @@ static void smbd_release_ip_immediate(struct tevent_context *ctx, struct smbd_release_ip_state *state = talloc_get_type_abort(private_data, struct smbd_release_ip_state); + struct smbXsrv_connection *xconn = state->sconn->conn; - if (!NT_STATUS_EQUAL(state->sconn->status, NT_STATUS_ADDRESS_CLOSED)) { + if (!NT_STATUS_EQUAL(xconn->transport.status, NT_STATUS_ADDRESS_CLOSED)) { /* * smbd_server_connection_terminate() already triggered ? */ @@ -2535,10 +2537,11 @@ static bool release_ip(const char *ip, void *priv) struct smbd_release_ip_state *state = talloc_get_type_abort(priv, struct smbd_release_ip_state); + struct smbXsrv_connection *xconn = state->sconn->conn; const char *addr = state->addr; const char *p = addr; - if (!NT_STATUS_IS_OK(state->sconn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* avoid recursion */ return false; } @@ -2580,7 +2583,7 @@ static bool release_ip(const char *ip, void *priv) /* * Make sure we don't get any io on the connection. */ - state->sconn->status = NT_STATUS_ADDRESS_CLOSED; + xconn->transport.status = NT_STATUS_ADDRESS_CLOSED; return true; } diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 357c69a..4c91bfb 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -102,13 +102,13 @@ static void exit_server_common(enum server_exit_reason how, if (sconn) { NTSTATUS status; - if (NT_STATUS_IS_OK(sconn->status)) { + if (NT_STATUS_IS_OK(conn->transport.status)) { switch (how) { case SERVER_EXIT_ABNORMAL: - sconn->status = NT_STATUS_INTERNAL_ERROR; + conn->transport.status = NT_STATUS_INTERNAL_ERROR; break; case SERVER_EXIT_NORMAL: - sconn->status = NT_STATUS_LOCAL_DISCONNECT; + conn->transport.status = NT_STATUS_LOCAL_DISCONNECT; break; } } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 7290d98..bb52aae 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2923,10 +2923,11 @@ static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state) static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn) { struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state; + struct smbXsrv_connection *xconn = sconn->conn; size_t max_send_queue_len; size_t cur_send_queue_len; - if (!NT_STATUS_IS_OK(sconn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ @@ -3189,7 +3190,7 @@ static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, NTSTATUS status; NTTIME now; - if (!NT_STATUS_IS_OK(sconn->status)) { + if (!NT_STATUS_IS_OK(xconn->transport.status)) { /* * we're not supposed to do any io */ -- 1.7.9.5 From 817cadee219a2f7b17c1458ee67aa8ee5c5fa216 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 May 2014 10:27:50 +0200 Subject: [PATCH 10/20] s3:smbd: move sconn->smb1.negprot.* to xconn->smb1.negprot.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 25 +++++++++++---------- source3/smbd/negprot.c | 52 ++++++++++++++++++++++++-------------------- source3/smbd/process.c | 2 +- source3/smbd/reply.c | 6 +++-- source3/smbd/server_exit.c | 2 +- source3/smbd/sesssetup.c | 11 +++++----- 6 files changed, 53 insertions(+), 45 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 23ba8d52..f9b5715 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -348,6 +348,19 @@ struct smbXsrv_connection { struct { struct { + bool encrypted_passwords; + bool spnego; + struct auth4_context *auth_context; + bool done; + /* + * Size of the data we can receive. Set by us. + * Can be modified by the max xmit parameter. + */ + int max_recv; + } negprot; + } smb1; + struct { + struct { uint32_t capabilities; struct GUID guid; uint16_t security_mode; @@ -717,18 +730,6 @@ struct smbd_server_connection { } echo_handler; struct { - bool encrypted_passwords; - bool spnego; - struct auth4_context *auth_context; - bool done; - /* - * Size of the data we can receive. Set by us. - * Can be modified by the max xmit parameter. - */ - int max_recv; - } negprot; - - struct { uint16_t client_major; uint16_t client_minor; uint32_t client_cap_low; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 4cd12d8..8c657e1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -33,27 +33,28 @@ extern fstring remote_proto; static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8]) { + struct smbXsrv_connection *xconn = sconn->conn; NTSTATUS nt_status; /* We might be called more than once, multiple negprots are * permitted */ - if (sconn->smb1.negprot.auth_context) { + if (xconn->smb1.negprot.auth_context) { DEBUG(3, ("get challenge: is this a secondary negprot? " "sconn->negprot.auth_context is non-NULL!\n")); - TALLOC_FREE(sconn->smb1.negprot.auth_context); + TALLOC_FREE(xconn->smb1.negprot.auth_context); } DEBUG(10, ("get challenge: creating negprot_global_auth_context\n")); nt_status = make_auth4_context( - sconn, &sconn->smb1.negprot.auth_context); + xconn, &xconn->smb1.negprot.auth_context); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status))); smb_panic("cannot make_negprot_global_auth_context!"); } DEBUG(10, ("get challenge: getting challenge\n")); - sconn->smb1.negprot.auth_context->get_ntlm_challenge( - sconn->smb1.negprot.auth_context, buff); + xconn->smb1.negprot.auth_context->get_ntlm_challenge( + xconn->smb1.negprot.auth_context, buff); } /**************************************************************************** @@ -65,6 +66,7 @@ static void reply_lanman1(struct smb_request *req, uint16 choice) int secword=0; time_t t = time(NULL); struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; uint16_t raw; if (lp_async_smb_echo_handler()) { raw = 0; @@ -72,19 +74,19 @@ static void reply_lanman1(struct smb_request *req, uint16 choice) raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0); } - sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); + xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); secword |= NEGOTIATE_SECURITY_USER_LEVEL; - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } - reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0); + reply_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0); SSVAL(req->outbuf,smb_vwv0,choice); SSVAL(req->outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { get_challenge(sconn, (uint8 *)smb_buf(req->outbuf)); SSVAL(req->outbuf,smb_vwv11, 8); } @@ -93,7 +95,7 @@ static void reply_lanman1(struct smb_request *req, uint16 choice) /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(req->outbuf,smb_vwv2, sconn->smb1.negprot.max_recv); + SSVAL(req->outbuf,smb_vwv2, xconn->smb1.negprot.max_recv); SSVAL(req->outbuf,smb_vwv3, lp_max_mux()); /* maxmux */ SSVAL(req->outbuf,smb_vwv4, 1); SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support @@ -115,6 +117,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice) int secword=0; time_t t = time(NULL); struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; uint16_t raw; if (lp_async_smb_echo_handler()) { raw = 0; @@ -122,21 +125,21 @@ static void reply_lanman2(struct smb_request *req, uint16 choice) raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0); } - sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); + xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); secword |= NEGOTIATE_SECURITY_USER_LEVEL; - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } - reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0); + reply_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0); SSVAL(req->outbuf,smb_vwv0, choice); SSVAL(req->outbuf,smb_vwv1, secword); SIVAL(req->outbuf,smb_vwv6, getpid()); /* Create a token value and add it to the outgoing packet. */ - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { get_challenge(sconn, (uint8 *)smb_buf(req->outbuf)); SSVAL(req->outbuf,smb_vwv11, 8); } @@ -145,7 +148,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice) /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); - SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv); + SSVAL(req->outbuf,smb_vwv2,xconn->smb1.negprot.max_recv); SSVAL(req->outbuf,smb_vwv3,lp_max_mux()); SSVAL(req->outbuf,smb_vwv4,1); SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ @@ -159,6 +162,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice) DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; DATA_BLOB blob = data_blob_null; DATA_BLOB blob_out = data_blob_null; nstring dos_name; @@ -188,7 +192,7 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) TALLOC_FREE(gensec_security); } - sconn->smb1.negprot.spnego = true; + xconn->smb1.negprot.spnego = true; /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all @@ -250,10 +254,11 @@ static void reply_nt1(struct smb_request *req, uint16 choice) struct timespec ts; ssize_t ret; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; bool signing_desired = false; bool signing_required = false; - sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); + xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); /* Check the flags field to see if this is Vista. WinXP sets it and Vista does not. But we have to @@ -272,7 +277,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) /* do spnego in user level security if the client supports it and we can do encrypted passwords */ - if (sconn->smb1.negprot.encrypted_passwords && + if (xconn->smb1.negprot.encrypted_passwords && lp_use_spnego() && (req->flags2 & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; @@ -309,7 +314,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) capabilities |= CAP_DFS; secword |= NEGOTIATE_SECURITY_USER_LEVEL; - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } @@ -333,7 +338,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */ SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */ SIVAL(req->outbuf,smb_vwv3+1, - sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */ + xconn->smb1.negprot.max_recv); /* max buffer. LOTS! */ SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */ SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */ SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */ @@ -343,7 +348,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { uint8 chal[8]; /* note that we do not send a challenge at all if we are using plaintext */ @@ -516,14 +521,15 @@ void reply_negprot(struct smb_request *req) int i; size_t converted_size; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; START_PROFILE(SMBnegprot); - if (sconn->smb1.negprot.done) { + if (xconn->smb1.negprot.done) { END_PROFILE(SMBnegprot); exit_server_cleanly("multiple negprot's are not permitted"); } - sconn->smb1.negprot.done = true; + xconn->smb1.negprot.done = true; if (req->buflen == 0) { DEBUG(0, ("negprot got no protocols\n")); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index aa496de..c500096 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3685,7 +3685,7 @@ void smbd_process(struct tevent_context *ev_ctx, tmp = MAX(tmp, SMB_BUFFER_SIZE_MIN); tmp = MIN(tmp, SMB_BUFFER_SIZE_MAX); - sconn->smb1.negprot.max_recv = tmp; + conn->smb1.negprot.max_recv = tmp; sconn->smb1.sessions.done_sesssetup = false; sconn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 67c0f81..06a4635 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -694,6 +694,7 @@ void reply_tcon(struct smb_request *req) const char *p2; TALLOC_CTX *ctx = talloc_tos(); struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; NTTIME now = timeval_to_nttime(&req->request_time); START_PROFILE(SMBtcon); @@ -735,7 +736,7 @@ void reply_tcon(struct smb_request *req) } reply_outbuf(req, 2, 0); - SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv); + SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv); SSVAL(req->outbuf,smb_vwv1,conn->cnum); SSVAL(req->outbuf,smb_tid,conn->cnum); @@ -771,6 +772,7 @@ void reply_tcon_and_X(struct smb_request *req) bool session_key_updated = false; uint16_t optional_support = 0; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; START_PROFILE(SMBtconX); @@ -818,7 +820,7 @@ void reply_tcon_and_X(struct smb_request *req) return; } - if (sconn->smb1.negprot.encrypted_passwords) { + if (xconn->smb1.negprot.encrypted_passwords) { p = req->buf + passlen; } else { p = req->buf + passlen + 1; diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 4c91bfb..077b81a 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -113,7 +113,7 @@ static void exit_server_common(enum server_exit_reason how, } } - TALLOC_FREE(sconn->smb1.negprot.auth_context); + TALLOC_FREE(conn->smb1.negprot.auth_context); if (lp_log_writeable_files_on_exit()) { bool found = false; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 1a0cb5e..a908f69 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -590,11 +590,10 @@ void reply_sesssetup_and_X(struct smb_request *req) uint16_t action = 0; NTTIME now = timeval_to_nttime(&req->request_time); struct smbXsrv_session *session = NULL; - NTSTATUS nt_status; struct smbd_server_connection *sconn = req->sconn; - - bool doencrypt = sconn->smb1.negprot.encrypted_passwords; + struct smbXsrv_connection *xconn = sconn->conn; + bool doencrypt = xconn->smb1.negprot.encrypted_passwords; bool signing_allowed = false; bool signing_mandatory = false; @@ -627,7 +626,7 @@ void reply_sesssetup_and_X(struct smb_request *req) if (req->wct == 12 && (req->flags2 & FLAGS2_EXTENDED_SECURITY)) { - if (!sconn->smb1.negprot.spnego) { + if (!xconn->smb1.negprot.spnego) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt " "at SPNEGO session setup when it was not " "negotiated.\n")); @@ -837,7 +836,7 @@ void reply_sesssetup_and_X(struct smb_request *req) domain, user, get_remote_machine_name())); if (*user) { - if (sconn->smb1.negprot.spnego) { + if (xconn->smb1.negprot.spnego) { /* This has to be here, because this is a perfectly * valid behaviour for guest logons :-( */ @@ -865,7 +864,7 @@ void reply_sesssetup_and_X(struct smb_request *req) } else if (doencrypt) { struct auth4_context *negprot_auth_context = NULL; - negprot_auth_context = sconn->smb1.negprot.auth_context; + negprot_auth_context = xconn->smb1.negprot.auth_context; if (!negprot_auth_context) { DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted " "session setup without negprot denied!\n")); -- 1.7.9.5 From 3e3953e1c3713ec14afdd4b02ce89d321424fd3b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 May 2014 10:56:26 +0200 Subject: [PATCH 11/20] s3:smbd: move sconn->smb1.sessions.* to xconn->smb1.sessions.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 19 ++++++++++--------- source3/smbd/ipc.c | 3 ++- source3/smbd/nttrans.c | 3 ++- source3/smbd/process.c | 4 ++-- source3/smbd/reply.c | 23 ++++++++++++++--------- source3/smbd/sesssetup.c | 17 +++++++++-------- source3/smbd/trans2.c | 3 ++- 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index f9b5715..096eef4 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -358,6 +358,16 @@ struct smbXsrv_connection { */ int max_recv; } negprot; + + struct { + bool done_sesssetup; + /* + * Size of data we can send to client. Set + * by the client for all protocols above CORE. + * Set by us for CORE protocol. + */ + int max_send; + } sessions; } smb1; struct { struct { @@ -736,15 +746,6 @@ struct smbd_server_connection { uint32_t client_cap_high; } unix_info; - struct { - bool done_sesssetup; - /* - * Size of data we can send to client. Set - * by the client for all protocols above CORE. - * Set by us for CORE protocol. - */ - int max_send; - } sessions; struct smb_signing_state *signing_state; struct notify_mid_map *notify_mid_maps; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index dbb259c..1c8033d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -108,7 +108,8 @@ void send_trans_reply(connection_struct *conn, int ldata = rdata ? rdata_len : 0; int lparam = rparam ? rparam_len : 0; struct smbd_server_connection *sconn = req->sconn; - int max_send = sconn->smb1.sessions.max_send; + struct smbXsrv_connection *xconn = sconn->conn; + int max_send = xconn->smb1.sessions.max_send; /* HACK: make sure we send at least 128 byte in one go */ int hdr_overhead = SMB_BUFFER_SIZE_MIN - 128; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bca4cd8..018a89d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -68,7 +68,8 @@ static void send_nt_replies(connection_struct *conn, int alignment_offset = 1; int data_alignment_offset = 0; struct smbd_server_connection *sconn = req->sconn; - int max_send = sconn->smb1.sessions.max_send; + struct smbXsrv_connection *xconn = sconn->conn; + int max_send = xconn->smb1.sessions.max_send; /* * If there genuinely are no parameters or data to send just send diff --git a/source3/smbd/process.c b/source3/smbd/process.c index c500096..f332277 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3687,8 +3687,8 @@ void smbd_process(struct tevent_context *ev_ctx, conn->smb1.negprot.max_recv = tmp; - sconn->smb1.sessions.done_sesssetup = false; - sconn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX; + conn->smb1.sessions.done_sesssetup = false; + conn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX; if (!init_dptrs(sconn)) { exit_server("init_dptrs() failed"); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 06a4635..d7d9f1c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1556,6 +1556,7 @@ void reply_search(struct smb_request *req) bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); struct dptr_struct *dirptr = NULL; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; START_PROFILE(SMBsearch); @@ -1705,7 +1706,7 @@ void reply_search(struct smb_request *req) } else { unsigned int i; size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf); - size_t available_space = sconn->smb1.sessions.max_send - hdr_size; + size_t available_space = xconn->smb1.sessions.max_send - hdr_size; maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE); @@ -3478,6 +3479,7 @@ void reply_lockread(struct smb_request *req) struct byte_range_lock *br_lck = NULL; char *p = NULL; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; START_PROFILE(SMBlockread); @@ -3533,13 +3535,13 @@ void reply_lockread(struct smb_request *req) /* * However the requested READ size IS affected by max_send. Insanity.... JRA. */ - maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3); + maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3); if (numtoread > maxtoread) { DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \ Returning short read of maximum allowed for compatibility with Windows 2000.\n", (unsigned int)numtoread, (unsigned int)maxtoread, - (unsigned int)sconn->smb1.sessions.max_send)); + (unsigned int)xconn->smb1.sessions.max_send)); numtoread = maxtoread; } @@ -3588,6 +3590,7 @@ void reply_read(struct smb_request *req) files_struct *fsp; struct lock_struct lock; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; START_PROFILE(SMBread); @@ -3616,13 +3619,13 @@ void reply_read(struct smb_request *req) /* * The requested read size cannot be greater than max_send. JRA. */ - maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3); + maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3); if (numtoread > maxtoread) { DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \ Returning short read of maximum allowed for compatibility with Windows 2000.\n", (unsigned int)numtoread, (unsigned int)maxtoread, - (unsigned int)sconn->smb1.sessions.max_send)); + (unsigned int)xconn->smb1.sessions.max_send)); numtoread = maxtoread; } @@ -3894,16 +3897,18 @@ nosendfile_read: static size_t calc_max_read_pdu(const struct smb_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; + if (req->sconn->conn->protocol < PROTOCOL_NT1) { - return req->sconn->smb1.sessions.max_send; + return xconn->smb1.sessions.max_send; } if (!lp_large_readwrite()) { - return req->sconn->smb1.sessions.max_send; + return xconn->smb1.sessions.max_send; } if (req_is_in_chain(req)) { - return req->sconn->smb1.sessions.max_send; + return xconn->smb1.sessions.max_send; } if (req->encrypted) { @@ -3912,7 +3917,7 @@ static size_t calc_max_read_pdu(const struct smb_request *req) * limit. There are padding considerations * that make that tricky. */ - return req->sconn->smb1.sessions.max_send; + return xconn->smb1.sessions.max_send; } if (srv_is_signing_active(req->sconn)) { diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a908f69..75da143 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -132,6 +132,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) uint64_t vuid = req->vuid; NTSTATUS status = NT_STATUS_OK; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; uint16_t action = 0; NTTIME now = timeval_to_nttime(&req->request_time); struct smbXsrv_session *session = NULL; @@ -140,7 +141,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) DEBUG(3,("Doing spnego session setup\n")); - if (!sconn->smb1.sessions.done_sesssetup) { + if (!xconn->smb1.sessions.done_sesssetup) { global_client_caps = client_caps; if (!(global_client_caps & CAP_STATUS32)) { @@ -381,13 +382,13 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) return; } - if (!sconn->smb1.sessions.done_sesssetup) { + if (!xconn->smb1.sessions.done_sesssetup) { if (smb_bufsize < SMB_BUFFER_SIZE_MIN) { reply_force_doserror(req, ERRSRV, ERRerror); return; } - sconn->smb1.sessions.max_send = smb_bufsize; - sconn->smb1.sessions.done_sesssetup = true; + xconn->smb1.sessions.max_send = smb_bufsize; + xconn->smb1.sessions.done_sesssetup = true; } /* current_user_info is changed on new vuid */ @@ -683,7 +684,7 @@ void reply_sesssetup_and_X(struct smb_request *req) const uint8_t *save_p = req->buf; uint16 byte_count; - if (!sconn->smb1.sessions.done_sesssetup) { + if (!xconn->smb1.sessions.done_sesssetup) { global_client_caps = IVAL(req->vwv+11, 0); if (!(global_client_caps & CAP_STATUS32)) { @@ -1090,14 +1091,14 @@ void reply_sesssetup_and_X(struct smb_request *req) SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid); req->vuid = sess_vuid; - if (!sconn->smb1.sessions.done_sesssetup) { + if (!xconn->smb1.sessions.done_sesssetup) { if (smb_bufsize < SMB_BUFFER_SIZE_MIN) { reply_force_doserror(req, ERRSRV, ERRerror); END_PROFILE(SMBsesssetupX); return; } - sconn->smb1.sessions.max_send = smb_bufsize; - sconn->smb1.sessions.done_sesssetup = true; + xconn->smb1.sessions.max_send = smb_bufsize; + xconn->smb1.sessions.done_sesssetup = true; } END_PROFILE(SMBsesssetupX); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4afb27e..1ab3f63 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -860,7 +860,8 @@ void send_trans2_replies(connection_struct *conn, int data_alignment_offset = 0; bool overflow = False; struct smbd_server_connection *sconn = req->sconn; - int max_send = sconn->smb1.sessions.max_send; + struct smbXsrv_connection *xconn = sconn->conn; + int max_send = xconn->smb1.sessions.max_send; /* Modify the data_to_send and datasize and set the error if we're trying to send more than max_data_bytes. We still send -- 1.7.9.5 From 02132b491bb19a8912c2864c1078e583c75fa74e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 May 2014 14:44:01 +0200 Subject: [PATCH 12/20] s3:smbd: move sconn->smb1.signing_state to xconn->smb1.signing_state This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 3 +-- source3/smbd/negprot.c | 4 ++-- source3/smbd/nttrans.c | 4 +++- source3/smbd/process.c | 10 ++++++---- source3/smbd/proto.h | 18 ++++++++++-------- source3/smbd/reply.c | 11 ++++++----- source3/smbd/service.c | 3 ++- source3/smbd/sesssetup.c | 10 +++++----- source3/smbd/signing.c | 16 ++++++++-------- source3/smbd/trans2.c | 5 +++-- 10 files changed, 46 insertions(+), 38 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 096eef4..8ee0973 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -368,6 +368,7 @@ struct smbXsrv_connection { */ int max_send; } sessions; + struct smb_signing_state *signing_state; } smb1; struct { struct { @@ -746,8 +747,6 @@ struct smbd_server_connection { uint32_t client_cap_high; } unix_info; - struct smb_signing_state *signing_state; - struct notify_mid_map *notify_mid_maps; struct { diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 8c657e1..63b3d36 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -318,8 +318,8 @@ static void reply_nt1(struct smb_request *req, uint16 choice) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } - signing_desired = smb_signing_is_desired(req->sconn->smb1.signing_state); - signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state); + signing_desired = smb_signing_is_desired(xconn->smb1.signing_state); + signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state); if (signing_desired) { secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 018a89d..57c4159 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1339,12 +1339,14 @@ static void call_nt_transact_create(connection_struct *conn, void reply_ntcancel(struct smb_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; + /* * Go through and cancel any pending change notifies. */ START_PROFILE(SMBntcancel); - srv_cancel_sign_response(req->sconn); + srv_cancel_sign_response(xconn); remove_pending_change_notify_requests_by_mid(req->sconn, req->mid); remove_pending_lock_requests_by_mid_smb1(req->sconn, req->mid); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f332277..92711dc 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -164,7 +164,7 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, if (do_signing) { /* Sign the outgoing packet if required. */ - srv_calculate_sign_mac(sconn, buf_out, seqnum); + srv_calculate_sign_mac(xconn, buf_out, seqnum); } if (do_encrypt) { @@ -414,6 +414,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, char **buffer, unsigned int timeout, size_t *p_unread, size_t *plen) { + struct smbXsrv_connection *xconn = sconn->conn; char lenbuf[4]; size_t len; int min_recv_size = lp_min_receive_file_size(); @@ -430,7 +431,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (CVAL(lenbuf,0) == 0 && min_recv_size && (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */ (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) && - !srv_is_signing_active(sconn) && + !srv_is_signing_active(xconn) && sconn->smb1.echo_handler.trusted_fde == NULL) { return receive_smb_raw_talloc_partial_read( @@ -474,6 +475,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, uint32_t *seqnum, bool trusted_channel) { + struct smbXsrv_connection *xconn = sconn->conn; size_t len = 0; NTSTATUS status; @@ -503,7 +505,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, } /* Check the incoming SMB signature. */ - if (!srv_check_sign_mac(sconn, *buffer, seqnum, trusted_channel)) { + if (!srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); return NT_STATUS_INVALID_NETWORK_RESPONSE; @@ -3595,7 +3597,7 @@ void smbd_process(struct tevent_context *ev_ctx, DEBUG(0,("Changed root to %s\n", lp_root_directory(talloc_tos()))); } - if (!srv_init_signing(sconn)) { + if (!srv_init_signing(conn)) { exit_server("Failed to init smb_signing"); } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index f598816..d93d446 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -48,17 +48,19 @@ /* The following definitions come from smbd/signing.c */ -bool srv_check_sign_mac(struct smbd_server_connection *conn, +struct smbXsrv_connection; + +bool srv_check_sign_mac(struct smbXsrv_connection *conn, const char *inbuf, uint32_t *seqnum, bool trusted_channel); -void srv_calculate_sign_mac(struct smbd_server_connection *conn, +void srv_calculate_sign_mac(struct smbXsrv_connection *conn, char *outbuf, uint32_t seqnum); -void srv_cancel_sign_response(struct smbd_server_connection *conn); -bool srv_init_signing(struct smbd_server_connection *conn); -void srv_set_signing_negotiated(struct smbd_server_connection *conn, +void srv_cancel_sign_response(struct smbXsrv_connection *conn); +bool srv_init_signing(struct smbXsrv_connection *conn); +void srv_set_signing_negotiated(struct smbXsrv_connection *conn, bool allowed, bool mandatory); -bool srv_is_signing_active(struct smbd_server_connection *conn); -bool srv_is_signing_negotiated(struct smbd_server_connection *conn); -void srv_set_signing(struct smbd_server_connection *conn, +bool srv_is_signing_active(struct smbXsrv_connection *conn); +bool srv_is_signing_negotiated(struct smbXsrv_connection *conn); +void srv_set_signing(struct smbXsrv_connection *conn, const DATA_BLOB user_session_key, const DATA_BLOB response); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7d9f1c..8c57e54 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3212,7 +3212,7 @@ static void send_file_readbraw(connection_struct *conn, if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && - lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) { + lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { ssize_t sendfile_read = -1; char header[4]; DATA_BLOB header_blob; @@ -3324,6 +3324,7 @@ void reply_readbraw(struct smb_request *req) { connection_struct *conn = req->conn; struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; ssize_t maxcount,mincount; size_t nread = 0; off_t startpos; @@ -3333,7 +3334,7 @@ void reply_readbraw(struct smb_request *req) START_PROFILE(SMBreadbraw); - if (srv_is_signing_active(sconn) || req->encrypted) { + if (srv_is_signing_active(xconn) || req->encrypted) { exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - " "raw reads/writes are disallowed."); } @@ -3728,7 +3729,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, !req->encrypted && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && - lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) { + lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; @@ -3920,7 +3921,7 @@ static size_t calc_max_read_pdu(const struct smb_request *req) return xconn->smb1.sessions.max_send; } - if (srv_is_signing_active(req->sconn)) { + if (srv_is_signing_active(xconn)) { return 0x1FFFF; } @@ -4143,7 +4144,7 @@ void reply_writebraw(struct smb_request *req) */ SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec); - if (srv_is_signing_active(req->sconn)) { + if (srv_is_signing_active(xconn)) { END_PROFILE(SMBwritebraw); exit_server_cleanly("reply_writebraw: SMB signing is active - " "raw reads/writes are disallowed."); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a9ad847..6596d2f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -521,6 +521,7 @@ static NTSTATUS make_connection_snum(struct smbd_server_connection *sconn, int snum, struct user_struct *vuser, const char *pdev) { + struct smbXsrv_connection *xconn = sconn->conn; struct smb_filename *smb_fname_cpath = NULL; fstring dev; int ret; @@ -857,7 +858,7 @@ static NTSTATUS make_connection_snum(struct smbd_server_connection *sconn, dbgtext( "%s (%s) ", get_remote_machine_name(), tsocket_address_string(conn->sconn->remote_address, talloc_tos()) ); - dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : ""); + dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(talloc_tos(), snum) ); dbgtext( "initially as user %s ", diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 75da143..43be24a 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -331,7 +331,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) register_homes_share(session_info->unix_info->unix_name); } - if (srv_is_signing_negotiated(sconn) && + if (srv_is_signing_negotiated(xconn) && action == 0 && session->global->signing_key.length > 0) { @@ -339,7 +339,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) * Try and turn on server signing on the first non-guest * sessionsetup. */ - srv_set_signing(sconn, + srv_set_signing(xconn, session->global->signing_key, data_blob_null); } @@ -618,7 +618,7 @@ void reply_sesssetup_and_X(struct smb_request *req) * It finds out when it needs to turn into a noop * itself. */ - srv_set_signing_negotiated(req->sconn, + srv_set_signing_negotiated(xconn, signing_allowed, signing_mandatory); @@ -1029,7 +1029,7 @@ void reply_sesssetup_and_X(struct smb_request *req) register_homes_share(session_info->unix_info->unix_name); } - if (srv_is_signing_negotiated(sconn) && + if (srv_is_signing_negotiated(xconn) && action == 0 && session->global->signing_key.length > 0) { @@ -1037,7 +1037,7 @@ void reply_sesssetup_and_X(struct smb_request *req) * Try and turn on server signing on the first non-guest * sessionsetup. */ - srv_set_signing(sconn, + srv_set_signing(xconn, session->global->signing_key, nt_resp.data ? nt_resp : lm_resp); } diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c index b7683cd..9fac87b 100644 --- a/source3/smbd/signing.c +++ b/source3/smbd/signing.c @@ -29,7 +29,7 @@ Called to validate an incoming packet from the client. ************************************************************/ -bool srv_check_sign_mac(struct smbd_server_connection *conn, +bool srv_check_sign_mac(struct smbXsrv_connection *conn, const char *inbuf, uint32_t *seqnum, bool trusted_channel) { @@ -75,7 +75,7 @@ bool srv_check_sign_mac(struct smbd_server_connection *conn, Called to sign an outgoing packet to the client. ************************************************************/ -void srv_calculate_sign_mac(struct smbd_server_connection *conn, +void srv_calculate_sign_mac(struct smbXsrv_connection *conn, char *outbuf, uint32_t seqnum) { uint8_t *outhdr; @@ -96,7 +96,7 @@ void srv_calculate_sign_mac(struct smbd_server_connection *conn, /*********************************************************** Called to indicate a oneway request ************************************************************/ -void srv_cancel_sign_response(struct smbd_server_connection *conn) +void srv_cancel_sign_response(struct smbXsrv_connection *conn) { smb_signing_cancel_reply(conn->smb1.signing_state, true); } @@ -167,7 +167,7 @@ static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr) Called by server negprot when signing has been negotiated. ************************************************************/ -bool srv_init_signing(struct smbd_server_connection *conn) +bool srv_init_signing(struct smbXsrv_connection *conn) { bool allowed = true; bool desired; @@ -229,7 +229,7 @@ bool srv_init_signing(struct smbd_server_connection *conn) return true; } -void srv_set_signing_negotiated(struct smbd_server_connection *conn, +void srv_set_signing_negotiated(struct smbXsrv_connection *conn, bool allowed, bool mandatory) { smb_signing_set_negotiated(conn->smb1.signing_state, @@ -241,7 +241,7 @@ void srv_set_signing_negotiated(struct smbd_server_connection *conn, reads/writes if it is. ************************************************************/ -bool srv_is_signing_active(struct smbd_server_connection *conn) +bool srv_is_signing_active(struct smbXsrv_connection *conn) { return smb_signing_is_active(conn->smb1.signing_state); } @@ -252,7 +252,7 @@ bool srv_is_signing_active(struct smbd_server_connection *conn) in the negprot. ************************************************************/ -bool srv_is_signing_negotiated(struct smbd_server_connection *conn) +bool srv_is_signing_negotiated(struct smbXsrv_connection *conn) { return smb_signing_is_negotiated(conn->smb1.signing_state); } @@ -261,7 +261,7 @@ bool srv_is_signing_negotiated(struct smbd_server_connection *conn) Turn on signing from this packet onwards. ************************************************************/ -void srv_set_signing(struct smbd_server_connection *conn, +void srv_set_signing(struct smbXsrv_connection *conn, const DATA_BLOB user_session_key, const DATA_BLOB response) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1ab3f63..7902b1d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3074,6 +3074,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, char **ppdata, int *ret_data_len) { + struct smbXsrv_connection *xconn = conn->sconn->conn; char *pdata, *end_data; int data_len = 0, len; const char *vname = volume_label(talloc_tos(), SNUM(conn)); @@ -3446,8 +3447,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case SMB_QUERY_CIFS_UNIX_INFO: { bool large_write = lp_min_receive_file_size() && - !srv_is_signing_active(conn->sconn); - bool large_read = !srv_is_signing_active(conn->sconn); + !srv_is_signing_active(xconn); + bool large_read = !srv_is_signing_active(xconn); int encrypt_caps = 0; if (!lp_unix_extensions()) { -- 1.7.9.5 From 39a613edd8ddf0079db666363e56814976cfe14d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 09:26:26 +0200 Subject: [PATCH 13/20] s3:smbd: move sconn->smb1.echo_handler.* to xconn->smb1.echo_handler.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 48 ++++++++++++++++++++-------------------- source3/smbd/msdfs.c | 2 -- source3/smbd/process.c | 57 +++++++++++++++++++++++++----------------------- source3/smbd/reply.c | 4 ++-- source3/smbd/trans2.c | 3 ++- 5 files changed, 58 insertions(+), 56 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 8ee0973..ceac066 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -348,6 +348,30 @@ struct smbXsrv_connection { struct { struct { + /* + * fd for the fcntl lock mutexing access to our sock + */ + int socket_lock_fd; + + /* + * fd for the trusted pipe from + * echo handler child + */ + int trusted_fd; + + /* + * fde for the trusted_fd + */ + struct tevent_fd *trusted_fde; + + /* + * Reference count for the fcntl lock to + * allow recursive locks. + */ + int ref_count; + } echo_handler; + + struct { bool encrypted_passwords; bool spnego; struct auth4_context *auth_context; @@ -717,30 +741,6 @@ struct smbd_server_connection { struct { struct { - /* - * fd for the fcntl lock mutexing access to our sock - */ - int socket_lock_fd; - - /* - * fd for the trusted pipe from - * echo handler child - */ - int trusted_fd; - - /* - * fde for the trusted_fd - */ - struct tevent_fd *trusted_fde; - - /* - * Reference count for the fcntl lock to - * allow recursive locks. - */ - int ref_count; - } echo_handler; - - struct { uint16_t client_major; uint16_t client_minor; uint32_t client_cap_low; diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6cf506c..835eabc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -246,8 +246,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx, sconn->ev_ctx = ev; sconn->msg_ctx = msg; - sconn->smb1.echo_handler.trusted_fd = -1; - sconn->smb1.echo_handler.socket_lock_fd = -1; conn = conn_new(sconn); if (conn == NULL) { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 92711dc..3c64b2c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -63,15 +63,16 @@ static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf); static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; bool ok; - if (sconn->smb1.echo_handler.socket_lock_fd == -1) { + if (xconn->smb1.echo_handler.socket_lock_fd == -1) { return true; } - sconn->smb1.echo_handler.ref_count++; + xconn->smb1.echo_handler.ref_count++; - if (sconn->smb1.echo_handler.ref_count > 1) { + if (xconn->smb1.echo_handler.ref_count > 1) { return true; } @@ -79,7 +80,7 @@ static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn) do { ok = fcntl_lock( - sconn->smb1.echo_handler.socket_lock_fd, + xconn->smb1.echo_handler.socket_lock_fd, F_SETLKW, 0, 0, F_WRLCK); } while (!ok && (errno == EINTR)); @@ -102,21 +103,22 @@ void smbd_lock_socket(struct smbd_server_connection *sconn) static bool smbd_unlock_socket_internal(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; bool ok; - if (sconn->smb1.echo_handler.socket_lock_fd == -1) { + if (xconn->smb1.echo_handler.socket_lock_fd == -1) { return true; } - sconn->smb1.echo_handler.ref_count--; + xconn->smb1.echo_handler.ref_count--; - if (sconn->smb1.echo_handler.ref_count > 0) { + if (xconn->smb1.echo_handler.ref_count > 0) { return true; } do { ok = fcntl_lock( - sconn->smb1.echo_handler.socket_lock_fd, + xconn->smb1.echo_handler.socket_lock_fd, F_SETLKW, 0, 0, F_UNLCK); } while (!ok && (errno == EINTR)); @@ -432,7 +434,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */ (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) && !srv_is_signing_active(xconn) && - sconn->smb1.echo_handler.trusted_fde == NULL) { + xconn->smb1.echo_handler.trusted_fde == NULL) { return receive_smb_raw_talloc_partial_read( mem_ctx, lenbuf, sconn, sock, buffer, timeout, @@ -2399,13 +2401,13 @@ static void smbd_server_connection_read_handler( bool from_client = false; if (async_echo) { - if (fd_is_readable(sconn->smb1.echo_handler.trusted_fd)) { + if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) { /* * This is the super-ugly hack to prefer the packets * forwarded by the echo handler over the ones by the * client directly */ - fd = sconn->smb1.echo_handler.trusted_fd; + fd = xconn->smb1.echo_handler.trusted_fd; } } @@ -2490,8 +2492,8 @@ static void smbd_server_echo_handler(struct tevent_context *ev, /* * we're not supposed to do any io */ - TEVENT_FD_NOT_READABLE(conn->smb1.echo_handler.trusted_fde); - TEVENT_FD_NOT_WRITEABLE(conn->smb1.echo_handler.trusted_fde); + TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde); + TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde); return; } @@ -2501,7 +2503,7 @@ static void smbd_server_echo_handler(struct tevent_context *ev, } if (flags & TEVENT_FD_READ) { smbd_server_connection_read_handler( - conn, conn->smb1.echo_handler.trusted_fd); + conn, xconn->smb1.echo_handler.trusted_fd); return; } } @@ -3142,6 +3144,7 @@ static void smbd_echo_got_packet(struct tevent_req *req) */ bool fork_echo_handler(struct smbd_server_connection *sconn) { + struct smbXsrv_connection *xconn = sconn->conn; int listener_pipe[2]; int res; pid_t child; @@ -3151,8 +3154,8 @@ bool fork_echo_handler(struct smbd_server_connection *sconn) DEBUG(1, ("pipe() failed: %s\n", strerror(errno))); return false; } - sconn->smb1.echo_handler.socket_lock_fd = create_unlink_tmp(lp_lock_directory()); - if (sconn->smb1.echo_handler.socket_lock_fd == -1) { + xconn->smb1.echo_handler.socket_lock_fd = create_unlink_tmp(lp_lock_directory()); + if (xconn->smb1.echo_handler.socket_lock_fd == -1) { DEBUG(1, ("Could not create lock fd: %s\n", strerror(errno))); goto fail; } @@ -3177,7 +3180,7 @@ bool fork_echo_handler(struct smbd_server_connection *sconn) } close(listener_pipe[1]); listener_pipe[1] = -1; - sconn->smb1.echo_handler.trusted_fd = listener_pipe[0]; + xconn->smb1.echo_handler.trusted_fd = listener_pipe[0]; DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child)); @@ -3185,13 +3188,13 @@ bool fork_echo_handler(struct smbd_server_connection *sconn) * Without smb signing this is the same as the normal smbd * listener. This needs to change once signing comes in. */ - sconn->smb1.echo_handler.trusted_fde = tevent_add_fd(sconn->ev_ctx, + xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(sconn->ev_ctx, sconn, - sconn->smb1.echo_handler.trusted_fd, + xconn->smb1.echo_handler.trusted_fd, TEVENT_FD_READ, smbd_server_echo_handler, sconn); - if (sconn->smb1.echo_handler.trusted_fde == NULL) { + if (xconn->smb1.echo_handler.trusted_fde == NULL) { DEBUG(1, ("event_add_fd failed\n")); goto fail; } @@ -3205,12 +3208,12 @@ fail: if (listener_pipe[1] != -1) { close(listener_pipe[1]); } - sconn->smb1.echo_handler.trusted_fd = -1; - if (sconn->smb1.echo_handler.socket_lock_fd != -1) { - close(sconn->smb1.echo_handler.socket_lock_fd); + xconn->smb1.echo_handler.trusted_fd = -1; + if (xconn->smb1.echo_handler.socket_lock_fd != -1) { + close(xconn->smb1.echo_handler.socket_lock_fd); } - sconn->smb1.echo_handler.trusted_fd = -1; - sconn->smb1.echo_handler.socket_lock_fd = -1; + xconn->smb1.echo_handler.trusted_fd = -1; + xconn->smb1.echo_handler.socket_lock_fd = -1; return false; } @@ -3415,6 +3418,8 @@ void smbd_process(struct tevent_context *ev_ctx, conn->ev_ctx = ev_ctx; conn->msg_ctx = msg_ctx; conn->transport.sock = sock_fd; + conn->smb1.echo_handler.trusted_fd = -1; + conn->smb1.echo_handler.socket_lock_fd = -1; sconn = talloc_zero(conn, struct smbd_server_connection); if (!sconn) { @@ -3431,8 +3436,6 @@ void smbd_process(struct tevent_context *ev_ctx, sconn->ev_ctx = ev_ctx; sconn->msg_ctx = msg_ctx; - sconn->smb1.echo_handler.trusted_fd = -1; - sconn->smb1.echo_handler.socket_lock_fd = -1; if (!interactive) { smbd_setup_sig_term_handler(sconn); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8c57e54..84e18d1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3345,7 +3345,7 @@ void reply_readbraw(struct smb_request *req) return; } - if (sconn->smb1.echo_handler.trusted_fde) { + if (xconn->smb1.echo_handler.trusted_fde) { DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of " "'async smb echo handler = yes'\n")); reply_readbraw_error(sconn); @@ -4157,7 +4157,7 @@ void reply_writebraw(struct smb_request *req) return; } - if (req->sconn->smb1.echo_handler.trusted_fde) { + if (xconn->smb1.echo_handler.trusted_fde) { DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of " "'async smb echo handler = yes'\n")); reply_nterror(req, NT_STATUS_NOT_SUPPORTED); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7902b1d..405a86c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3709,6 +3709,7 @@ static void call_trans2setfsinfo(connection_struct *conn, unsigned int max_data_bytes) { struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; char *pdata = *ppdata; char *params = *pparams; uint16 info_level; @@ -3819,7 +3820,7 @@ static void call_trans2setfsinfo(connection_struct *conn, return; } - if (req->sconn->smb1.echo_handler.trusted_fde) { + if (xconn->smb1.echo_handler.trusted_fde) { DEBUG( 2,("call_trans2setfsinfo: " "request transport encryption disabled" "with 'fork echo handler = yes'\n")); -- 1.7.9.5 From 5e64afa7906ea5058bea4ba1042710d1682424d7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 09:36:24 +0200 Subject: [PATCH 14/20] s3:smb2_server: use xconn->transport.fde also for smb2 This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 1 - source3/smbd/smb2_server.c | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index ceac066..7d9abdc 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -778,7 +778,6 @@ struct smbd_server_connection { } request_read_state; struct smbd_smb2_send_queue *send_queue; size_t send_queue_len; - struct tevent_fd *fde; bool negprot_2ff; struct { /* The event that makes us process our blocking lock queue */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index bb52aae..100795c 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -216,13 +216,13 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) return NT_STATUS_NO_MEMORY; } - sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx, + xconn->transport.fde = tevent_add_fd(sconn->ev_ctx, sconn, xconn->transport.sock, TEVENT_FD_READ, smbd_smb2_connection_handler, sconn); - if (sconn->smb2.fde == NULL) { + if (xconn->transport.fde == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2963,7 +2963,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s state->req->sconn = sconn; state->min_recv_size = lp_min_receive_file_size(); - TEVENT_FD_READABLE(sconn->smb2.fde); + TEVENT_FD_READABLE(xconn->transport.fde); return NT_STATUS_OK; } @@ -3075,7 +3075,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) bool retry; if (sconn->smb2.send_queue == NULL) { - TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde); + TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde); return NT_STATUS_OK; } @@ -3130,7 +3130,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) err = socket_error_from_errno(ret, errno, &retry); if (retry) { /* retry later */ - TEVENT_FD_WRITEABLE(sconn->smb2.fde); + TEVENT_FD_WRITEABLE(xconn->transport.fde); return NT_STATUS_OK; } if (err != 0) { @@ -3165,7 +3165,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) if (e->count > 0) { /* we have more to write */ - TEVENT_FD_WRITEABLE(sconn->smb2.fde); + TEVENT_FD_WRITEABLE(xconn->transport.fde); return NT_STATUS_OK; } @@ -3194,8 +3194,8 @@ static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, /* * we're not supposed to do any io */ - TEVENT_FD_NOT_READABLE(sconn->smb2.fde); - TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde); + TEVENT_FD_NOT_READABLE(xconn->transport.fde); + TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde); return NT_STATUS_OK; } @@ -3211,7 +3211,7 @@ static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, } if (state->req == NULL) { - TEVENT_FD_NOT_READABLE(sconn->smb2.fde); + TEVENT_FD_NOT_READABLE(xconn->transport.fde); return NT_STATUS_OK; } @@ -3231,7 +3231,7 @@ again: err = socket_error_from_errno(ret, errno, &retry); if (retry) { /* retry later */ - TEVENT_FD_READABLE(sconn->smb2.fde); + TEVENT_FD_READABLE(xconn->transport.fde); return NT_STATUS_OK; } if (err != 0) { @@ -3245,7 +3245,7 @@ again: state->vector.iov_base = (void *)base; state->vector.iov_len -= ret; /* we have more to read */ - TEVENT_FD_READABLE(sconn->smb2.fde); + TEVENT_FD_READABLE(xconn->transport.fde); return NT_STATUS_OK; } -- 1.7.9.5 From 809f9b3b0892f11a22b98836690e35b8710c312b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 09:41:57 +0200 Subject: [PATCH 15/20] s3:smb2_server: move sconn->smb2.request_read_state to xconn->smb2.request_read_state This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 27 ++++++++++++++------------- source3/smbd/smb2_server.c | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 7d9abdc..c89376c 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -395,6 +395,20 @@ struct smbXsrv_connection { struct smb_signing_state *signing_state; } smb1; struct { + struct smbd_smb2_request_read_state { + struct smbd_smb2_request *req; + struct { + uint8_t nbt[NBT_HDR_SIZE]; + bool done; + } hdr; + struct iovec vector; + bool doing_receivefile; + size_t min_recv_size; + size_t pktfull; + size_t pktlen; + uint8_t *pktbuf; + } request_read_state; + struct { uint32_t capabilities; struct GUID guid; @@ -763,19 +777,6 @@ struct smbd_server_connection { } locks; } smb1; struct { - struct smbd_smb2_request_read_state { - struct smbd_smb2_request *req; - struct { - uint8_t nbt[NBT_HDR_SIZE]; - bool done; - } hdr; - struct iovec vector; - bool doing_receivefile; - size_t min_recv_size; - size_t pktfull; - size_t pktlen; - uint8_t *pktbuf; - } request_read_state; struct smbd_smb2_send_queue *send_queue; size_t send_queue_len; bool negprot_2ff; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 100795c..c8df062 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2922,8 +2922,8 @@ static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state) static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn) { - struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state; struct smbXsrv_connection *xconn = sconn->conn; + struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state; size_t max_send_queue_len; size_t cur_send_queue_len; @@ -3181,7 +3181,7 @@ static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, uint16_t fde_flags) { struct smbXsrv_connection *xconn = sconn->conn; - struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state; + struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state; struct smbd_smb2_request *req = NULL; size_t min_recvfile_size = UINT32_MAX; int ret; -- 1.7.9.5 From a94a3fe65a7e9249285a1746dcbd728d73618991 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 09:53:21 +0200 Subject: [PATCH 16/20] s3:smb2_server: move sconn->smb2.send_queue* to xconn->smb2.send_queue* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 4 ++-- source3/smbd/smb2_server.c | 35 +++++++++++++++++------------------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index c89376c..8deb782 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -408,6 +408,8 @@ struct smbXsrv_connection { size_t pktlen; uint8_t *pktbuf; } request_read_state; + struct smbd_smb2_send_queue *send_queue; + size_t send_queue_len; struct { uint32_t capabilities; @@ -777,8 +779,6 @@ struct smbd_server_connection { } locks; } smb1; struct { - struct smbd_smb2_send_queue *send_queue; - size_t send_queue_len; bool negprot_2ff; struct { /* The event that makes us process our blocking lock queue */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index c8df062..f0b872c 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -204,8 +204,6 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn) TALLOC_FREE(xconn->transport.fde); - sconn->smb2.send_queue = NULL; - sconn->smb2.seqnum_low = 0; sconn->smb2.seqnum_range = 1; sconn->smb2.credits_granted = 1; @@ -1263,8 +1261,8 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request nreq->queue_entry.mem_ctx = nreq; nreq->queue_entry.vector = nreq->out.vector; nreq->queue_entry.count = nreq->out.vector_count; - DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL); - nreq->sconn->smb2.send_queue_len++; + DLIST_ADD_END(conn->smb2.send_queue, &nreq->queue_entry, NULL); + conn->smb2.send_queue_len++; status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { @@ -1424,6 +1422,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, talloc_get_type_abort(private_data, struct smbd_smb2_request); struct smbd_server_connection *sconn = req->sconn; + struct smbXsrv_connection *xconn = sconn->conn; struct smbd_smb2_request_pending_state *state = NULL; uint8_t *outhdr = NULL; const uint8_t *inhdr = NULL; @@ -1596,8 +1595,8 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, state->queue_entry.mem_ctx = state; state->queue_entry.vector = state->vector; state->queue_entry.count = ARRAY_SIZE(state->vector); - DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL); - sconn->smb2.send_queue_len++; + DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL); + xconn->smb2.send_queue_len++; status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { @@ -2497,8 +2496,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) req->queue_entry.mem_ctx = req; req->queue_entry.vector = req->out.vector; req->queue_entry.count = req->out.vector_count; - DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL); - req->sconn->smb2.send_queue_len++; + DLIST_ADD_END(conn->smb2.send_queue, &req->queue_entry, NULL); + conn->smb2.send_queue_len++; status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { @@ -2828,8 +2827,8 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, state->queue_entry.mem_ctx = state; state->queue_entry.vector = state->vector; state->queue_entry.count = ARRAY_SIZE(state->vector); - DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL); - state->sconn->smb2.send_queue_len++; + DLIST_ADD_END(conn->smb2.send_queue, &state->queue_entry, NULL); + conn->smb2.send_queue_len++; status = smbd_smb2_flush_send_queue(sconn); if (!NT_STATUS_IS_OK(status)) { @@ -2943,7 +2942,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s } max_send_queue_len = MAX(1, sconn->smb2.max_credits/16); - cur_send_queue_len = sconn->smb2.send_queue_len; + cur_send_queue_len = xconn->smb2.send_queue_len; if (cur_send_queue_len > max_send_queue_len) { /* @@ -3074,13 +3073,13 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) int err; bool retry; - if (sconn->smb2.send_queue == NULL) { + if (xconn->smb2.send_queue == NULL) { TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde); return NT_STATUS_OK; } - while (sconn->smb2.send_queue != NULL) { - struct smbd_smb2_send_queue *e = sconn->smb2.send_queue; + while (xconn->smb2.send_queue != NULL) { + struct smbd_smb2_send_queue *e = xconn->smb2.send_queue; if (e->sendfile_header != NULL) { size_t size = 0; @@ -3112,8 +3111,8 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) e->sendfile_header->length = size; e->count = 0; - sconn->smb2.send_queue_len--; - DLIST_REMOVE(sconn->smb2.send_queue, e); + xconn->smb2.send_queue_len--; + DLIST_REMOVE(xconn->smb2.send_queue, e); /* * This triggers the sendfile path via * the destructor. @@ -3169,8 +3168,8 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) return NT_STATUS_OK; } - sconn->smb2.send_queue_len--; - DLIST_REMOVE(sconn->smb2.send_queue, e); + xconn->smb2.send_queue_len--; + DLIST_REMOVE(xconn->smb2.send_queue, e); talloc_free(e->mem_ctx); } -- 1.7.9.5 From 4748877048ed07d7182b2157cc2568b666f623f3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 10:07:21 +0200 Subject: [PATCH 17/20] s3:smb2_server: move sconn->smb2.negprot_2ff to xconn->smb2.allow_2ff This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 2 +- source3/smbd/smb2_negprot.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 8deb782..2efe68b 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -411,6 +411,7 @@ struct smbXsrv_connection { struct smbd_smb2_send_queue *send_queue; size_t send_queue_len; + bool allow_2ff; struct { uint32_t capabilities; struct GUID guid; @@ -779,7 +780,6 @@ struct smbd_server_connection { } locks; } smb1; struct { - bool negprot_2ff; struct { /* The event that makes us process our blocking lock queue */ struct tevent_timer *brl_timeout; diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 6643464..cc99b1d 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -78,12 +78,14 @@ void reply_smb2002(struct smb_request *req, uint16_t choice) */ void reply_smb20ff(struct smb_request *req, uint16_t choice) { - req->sconn->smb2.negprot_2ff = true; + struct smbXsrv_connection *xconn = req->sconn->conn; + xconn->smb2.allow_2ff = true; reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF); } NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; const uint8_t *indyn = NULL; @@ -220,8 +222,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) dialect = SVAL(indyn, c*2); if (dialect == SMB2_DIALECT_REVISION_2FF) { - if (req->sconn->smb2.negprot_2ff) { - req->sconn->smb2.negprot_2ff = false; + if (xconn->smb2.allow_2ff) { + xconn->smb2.allow_2ff = false; protocol = PROTOCOL_SMB2_10; break; } -- 1.7.9.5 From b8b39d8ab0a827934b557ae85c67502e254fb445 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 10:22:34 +0200 Subject: [PATCH 18/20] s3:smb2_server: use xconn->smb2.server.max_* instead of sconn->smb2.max_* We don't need this twice... Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 3 --- source3/smbd/smb2_find.c | 5 +++-- source3/smbd/smb2_getinfo.c | 9 +++++---- source3/smbd/smb2_negprot.c | 4 ---- source3/smbd/smb2_notify.c | 3 ++- source3/smbd/smb2_read.c | 5 +++-- source3/smbd/smb2_setinfo.c | 5 +++-- source3/smbd/smb2_write.c | 5 +++-- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 2efe68b..f7c1dc9 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -829,9 +829,6 @@ struct smbd_server_connection { */ struct bitmap *credits_bitmap; bool supports_multicredit; - uint32_t max_trans; - uint32_t max_read; - uint32_t max_write; } smb2; struct smbXsrv_connection *conn; diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 3f779b8..6eb3301 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -207,6 +207,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, uint32_t in_output_buffer_length, const char *in_file_name) { + struct smbXsrv_connection *xconn = smb2req->sconn->conn; struct tevent_req *req; struct smbd_smb2_find_state *state; struct smb_request *smbreq; @@ -272,11 +273,11 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - if (in_output_buffer_length > smb2req->sconn->smb2.max_trans) { + if (in_output_buffer_length > xconn->smb2.server.max_trans) { DEBUG(2,("smbd_smb2_find_send: " "client ignored max trans:%s: 0x%08X: 0x%08X\n", __location__, in_output_buffer_length, - smb2req->sconn->smb2.max_trans)); + xconn->smb2.server.max_trans)); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index ec6181a..275792c 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -44,6 +44,7 @@ static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req, static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; uint8_t in_info_type; @@ -90,18 +91,18 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) in_input_buffer.data = SMBD_SMB2_IN_DYN_PTR(req); in_input_buffer.length = in_input_buffer_length; - if (in_input_buffer.length > req->sconn->smb2.max_trans) { + if (in_input_buffer.length > xconn->smb2.server.max_trans) { DEBUG(2,("smbd_smb2_request_process_getinfo: " "client ignored max trans: %s: 0x%08X: 0x%08X\n", __location__, (unsigned)in_input_buffer.length, - (unsigned)req->sconn->smb2.max_trans)); + (unsigned)xconn->smb2.server.max_trans)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } - if (in_output_buffer_length > req->sconn->smb2.max_trans) { + if (in_output_buffer_length > xconn->smb2.server.max_trans) { DEBUG(2,("smbd_smb2_request_process_getinfo: " "client ignored max trans: %s: 0x%08X: 0x%08X\n", __location__, in_output_buffer_length, - req->sconn->smb2.max_trans)); + xconn->smb2.server.max_trans)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index cc99b1d..64bbe37 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -380,10 +380,6 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) conn->smb2.server.max_trans = max_trans; conn->smb2.server.max_read = max_read; conn->smb2.server.max_write = max_write; - - req->sconn->smb2.max_trans = max_trans; - req->sconn->smb2.max_read = max_read; - req->sconn->smb2.max_write = max_write; } return smbd_smb2_request_done(req, outbody, &outdyn); diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 7351d9f..3e33d42 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -48,6 +48,7 @@ static NTSTATUS smbd_smb2_notify_recv(struct tevent_req *req, static void smbd_smb2_request_notify_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; uint16_t in_flags; @@ -74,7 +75,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) * 0x00010000 is what Windows 7 uses, * Windows 2008 uses 0x00080000 */ - if (in_output_buffer_length > req->sconn->smb2.max_trans) { + if (in_output_buffer_length > xconn->smb2.server.max_trans) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index db8312b..f40cf29 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -43,6 +43,7 @@ static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req, static void smbd_smb2_request_read_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; uint32_t in_length; @@ -68,10 +69,10 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req) in_remaining_bytes = IVAL(inbody, 0x28); /* check the max read size */ - if (in_length > req->sconn->smb2.max_read) { + if (in_length > xconn->smb2.server.max_read) { DEBUG(2,("smbd_smb2_request_process_read: " "client ignored max read: %s: 0x%08X: 0x%08X\n", - __location__, in_length, req->sconn->smb2.max_read)); + __location__, in_length, xconn->smb2.server.max_read)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index 97872da..1b5e2a8 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -39,6 +39,7 @@ static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req); static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; uint8_t in_info_type; @@ -81,11 +82,11 @@ NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req) in_input_buffer.data = SMBD_SMB2_IN_DYN_PTR(req); in_input_buffer.length = in_input_buffer_length; - if (in_input_buffer.length > req->sconn->smb2.max_trans) { + if (in_input_buffer.length > xconn->smb2.server.max_trans) { DEBUG(2,("smbd_smb2_request_process_setinfo: " "client ignored max trans: %s: 0x%08X: 0x%08X\n", __location__, (unsigned)in_input_buffer.length, - (unsigned)req->sconn->smb2.max_trans)); + (unsigned)xconn->smb2.server.max_trans)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index c61254f..40a5937 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -38,6 +38,7 @@ static NTSTATUS smbd_smb2_write_recv(struct tevent_req *req, static void smbd_smb2_request_write_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req) { + struct smbXsrv_connection *xconn = req->sconn->conn; NTSTATUS status; const uint8_t *inbody; uint16_t in_data_offset; @@ -82,10 +83,10 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req) } /* check the max write size */ - if (in_data_length > req->sconn->smb2.max_write) { + if (in_data_length > xconn->smb2.server.max_write) { DEBUG(2,("smbd_smb2_request_process_write : " "client ignored max write :%s: 0x%08X: 0x%08X\n", - __location__, in_data_length, req->sconn->smb2.max_write)); + __location__, in_data_length, xconn->smb2.server.max_write)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } -- 1.7.9.5 From 46a9f160394b9c5dd9d0dc33bf46cd9356dabc97 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2014 12:10:23 +0200 Subject: [PATCH 19/20] s3:smb2_server: move sconn->smb2.*credits* to xconn->smb2.credits.* This prepares the structures for multi-channel support. Signed-off-by: Stefan Metzmacher --- 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 f7c1dc9..61fa5cd 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -411,6 +411,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; + /* + * 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 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 seqnum_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; @@ -786,49 +832,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; struct smbXsrv_connection *conn; diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 64bbe37..2a872aa 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -286,7 +286,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; /* SMB >= 2.1 has 1 MB of allowed size */ max_limit = 0x100000; /* 1MB */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index f0b872c..f3a06a8 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, @@ -1807,13 +1813,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); } @@ -2941,7 +2948,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) { -- 1.7.9.5 From 20b9bc15eb5c31aab5bdbd4f75c45f5f7919ad06 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 May 2014 19:47:13 +0200 Subject: [PATCH 20/20] s3:smbd: introduce 'struct smbXsrv_client' in order to prepare multi-channel support This structure is supposed to hold the global state shared between multiple connections from the same client. We'll step by step move things from smbXsrv_connection to smbXsrv_client. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.c | 2 +- source3/smbd/globals.h | 18 +++++++++++++++++- source3/smbd/process.c | 25 +++++++++++++++++++------ source3/smbd/server_exit.c | 10 ++++++++-- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 3eb65a1..63e8ea1 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -90,7 +90,7 @@ struct smbd_parent_context *am_parent = NULL; struct memcache *smbd_memcache_ctx = NULL; bool exit_firsttime = true; -struct smbXsrv_connection *global_smbXsrv_connection = NULL; +struct smbXsrv_client *global_smbXsrv_client = NULL; struct memcache *smbd_memcache(void) { diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 61fa5cd..71e2d29 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -324,7 +324,11 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req, char *private_data, size_t priv_len); +struct smbXsrv_client; + struct smbXsrv_connection { + struct smbXsrv_client *client; + struct smbd_server_connection *sconn; const struct tsocket_address *local_address; @@ -503,6 +507,18 @@ struct smbXsrv_connection { struct smbXsrv_open_table *open_table; }; +struct smbXsrv_client { + struct tevent_context *ev_ctx; + struct messaging_context *msg_ctx; + + /* + * For now this is only one connection! + * With multi-channel support we'll get more than + * one in future. + */ + struct smbXsrv_connection *connections; +}; + NTSTATUS smbXsrv_version_global_init(const struct server_id *server_id); uint32_t smbXsrv_version_global_current(void); @@ -837,6 +853,6 @@ struct smbd_server_connection { struct smbXsrv_connection *conn; }; -extern struct smbXsrv_connection *global_smbXsrv_connection; +extern struct smbXsrv_client *global_smbXsrv_client; void smbd_init_globals(void); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3c64b2c..35765fe 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3392,6 +3392,7 @@ void smbd_process(struct tevent_context *ev_ctx, bool interactive) { TALLOC_CTX *frame = talloc_stackframe(); + struct smbXsrv_client *client; struct smbXsrv_connection *conn; struct smbd_server_connection *sconn; struct sockaddr_storage ss_srv; @@ -3409,11 +3410,28 @@ void smbd_process(struct tevent_context *ev_ctx, int ret; int tmp; - conn = talloc_zero(ev_ctx, struct smbXsrv_connection); + client = talloc_zero(ev_ctx, struct smbXsrv_client); + if (client == NULL) { + DEBUG(0,("talloc_zero(struct smbXsrv_client)\n")); + exit_server_cleanly("talloc_zero(struct smbXsrv_client).\n"); + } + + /* + * TODO: remove this...:-) + */ + global_smbXsrv_client = client; + + client->ev_ctx = ev_ctx; + client->msg_ctx = msg_ctx; + + conn = talloc_zero(client, struct smbXsrv_connection); if (conn == NULL) { DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n")); exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n"); } + /* for now we only have one connection */ + client->connections = conn; + conn->client = client; conn->ev_ctx = ev_ctx; conn->msg_ctx = msg_ctx; @@ -3429,11 +3447,6 @@ void smbd_process(struct tevent_context *ev_ctx, conn->sconn = sconn; sconn->conn = conn; - /* - * TODO: remove this...:-) - */ - global_smbXsrv_connection = conn; - sconn->ev_ctx = ev_ctx; sconn->msg_ctx = msg_ctx; diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 077b81a..3a8a353 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -85,10 +85,15 @@ static void exit_server_common(enum server_exit_reason how, static void exit_server_common(enum server_exit_reason how, const char *reason) { - struct smbXsrv_connection *conn = global_smbXsrv_connection; + struct smbXsrv_client *client = global_smbXsrv_client; + struct smbXsrv_connection *conn = NULL; struct smbd_server_connection *sconn = NULL; struct messaging_context *msg_ctx = server_messaging_context(); + if (client != NULL) { + conn = client->connections; + } + if (conn != NULL) { sconn = conn->sconn; } @@ -202,7 +207,8 @@ static void exit_server_common(enum server_exit_reason how, */ sconn = NULL; conn = NULL; - TALLOC_FREE(global_smbXsrv_connection); + client = NULL; + TALLOC_FREE(global_smbXsrv_client); server_messaging_context_free(); server_event_context_free(); TALLOC_FREE(smbd_memcache_ctx); -- 1.7.9.5