svn commit: samba r17084 - in branches/SAMBA_4_0/source/smb_server:
. smb2
metze at samba.org
metze at samba.org
Mon Jul 17 09:44:15 GMT 2006
Author: metze
Date: 2006-07-17 09:44:13 +0000 (Mon, 17 Jul 2006)
New Revision: 17084
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17084
Log:
implement SMB2 Cancel in the server,
that makes it possible for clients to cancel
async requests, like NOTIFY...
metze
Modified:
branches/SAMBA_4_0/source/smb_server/smb2/fileio.c
branches/SAMBA_4_0/source/smb_server/smb2/receive.c
branches/SAMBA_4_0/source/smb_server/smb2/smb2_server.h
branches/SAMBA_4_0/source/smb_server/smb_server.h
Changeset:
Modified: branches/SAMBA_4_0/source/smb_server/smb2/fileio.c
===================================================================
--- branches/SAMBA_4_0/source/smb_server/smb2/fileio.c 2006-07-17 09:36:52 UTC (rev 17083)
+++ branches/SAMBA_4_0/source/smb_server/smb2/fileio.c 2006-07-17 09:44:13 UTC (rev 17084)
@@ -286,11 +286,6 @@
SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
}
-void smb2srv_cancel_recv(struct smb2srv_request *req)
-{
- smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED);
-}
-
static void smb2srv_notify_send(struct ntvfs_request *ntvfs)
{
struct smb2srv_request *req;
Modified: branches/SAMBA_4_0/source/smb_server/smb2/receive.c
===================================================================
--- branches/SAMBA_4_0/source/smb_server/smb2/receive.c 2006-07-17 09:36:52 UTC (rev 17083)
+++ branches/SAMBA_4_0/source/smb_server/smb2/receive.c 2006-07-17 09:44:13 UTC (rev 17084)
@@ -28,8 +28,22 @@
#include "smb_server/smb2/smb2_server.h"
#include "smbd/service_stream.h"
#include "lib/stream/packet.h"
+#include "ntvfs/ntvfs.h"
+static int smb2srv_request_destructor(struct smb2srv_request *req)
+{
+ DLIST_REMOVE(req->smb_conn->requests2.list, req);
+ if (req->pending_id) {
+ idr_remove(req->smb_conn->requests2.idtree_req, req->pending_id);
+ }
+ return 0;
+}
+static int smb2srv_request_deny_destructor(struct smb2srv_request *req)
+{
+ return -1;
+}
+
static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn)
{
struct smb2srv_request *req;
@@ -39,12 +53,24 @@
req->smb_conn = smb_conn;
+ talloc_set_destructor(req, smb2srv_request_destructor);
+
return req;
}
NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size,
BOOL body_dynamic_present, uint32_t body_dynamic_size)
{
+ uint32_t flags = 0x00000001;
+ uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID);
+ uint32_t tid = IVAL(req->in.hdr, SMB2_HDR_TID);
+
+ if (req->pending_id) {
+ flags |= 0x00000002;
+ pid = req->pending_id;
+ tid = 0;
+ }
+
if (body_dynamic_present) {
if (body_dynamic_size == 0) {
body_dynamic_size = 1;
@@ -71,11 +97,11 @@
SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status));
SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE));
SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,0x0001);
- SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0x00000001);
+ SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags);
SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN2,0);
SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum);
- SIVAL(req->out.hdr, SMB2_HDR_PID, IVAL(req->in.hdr, SMB2_HDR_PID));
- SIVAL(req->out.hdr, SMB2_HDR_TID, IVAL(req->in.hdr, SMB2_HDR_TID));
+ SIVAL(req->out.hdr, SMB2_HDR_PID, pid);
+ SIVAL(req->out.hdr, SMB2_HDR_TID, tid);
SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID));
memset(req->out.hdr+SMB2_HDR_SIG, 0, 16);
@@ -216,8 +242,6 @@
smb2srv_ioctl_recv(req);
return NT_STATUS_OK;
case SMB2_OP_CANCEL:
- if (!req->session) goto nosession;
- if (!req->tcon) goto notcon;
smb2srv_cancel_recv(req);
return NT_STATUS_OK;
case SMB2_OP_KEEPALIVE:
@@ -329,6 +353,72 @@
return smb2srv_reply(req);
}
+static NTSTATUS smb2srv_init_pending(struct smbsrv_connection *smb_conn)
+{
+ smb_conn->requests2.idtree_req = idr_init(smb_conn);
+ NT_STATUS_HAVE_NO_MEMORY(smb_conn->requests2.idtree_req);
+ smb_conn->requests2.idtree_limit = 0x00FFFFFF & (UINT32_MAX - 1);
+ smb_conn->requests2.list = NULL;
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req)
+{
+ int id;
+
+ if (req->pending_id) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ id = idr_get_new_above(req->smb_conn->requests2.idtree_req, req,
+ 1, req->smb_conn->requests2.idtree_limit);
+ if (id == -1) {
+ return NT_STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ DLIST_ADD_END(req->smb_conn->requests2.list, req, struct smb2srv_request *);
+ req->pending_id = id;
+
+ talloc_set_destructor(req, smb2srv_request_deny_destructor);
+ smb2srv_send_error(req, STATUS_PENDING);
+ talloc_set_destructor(req, smb2srv_request_destructor);
+
+ return NT_STATUS_OK;
+}
+
+void smb2srv_cancel_recv(struct smb2srv_request *req)
+{
+ uint32_t pending_id;
+ uint32_t flags;
+ void *p;
+ struct smb2srv_request *r;
+
+ if (!req->session) goto done;
+
+ flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS);
+ pending_id = IVAL(req->in.hdr, SMB2_HDR_PID);
+
+ if (!(flags & 0x00000002)) {
+ /* TODO: what to do here? */
+ goto done;
+ }
+
+ p = idr_find(req->smb_conn->requests2.idtree_req, pending_id);
+ if (!p) goto done;
+
+ r = talloc_get_type(p, struct smb2srv_request);
+ if (!r) goto done;
+
+ if (!r->ntvfs) goto done;
+
+ ntvfs_cancel(r->ntvfs);
+
+done:
+ /* we never generate a reply for a SMB2 Cancel */
+ talloc_free(req);
+}
+
/*
* init the SMB2 protocol related stuff
*/
@@ -351,6 +441,9 @@
status = smbsrv_init_sessions(smb_conn, UINT64_MAX);
NT_STATUS_NOT_OK_RETURN(status);
+ status = smb2srv_init_pending(smb_conn);
+ NT_STATUS_NOT_OK_RETURN(status);
+
return NT_STATUS_OK;
}
Modified: branches/SAMBA_4_0/source/smb_server/smb2/smb2_server.h
===================================================================
--- branches/SAMBA_4_0/source/smb_server/smb2/smb2_server.h 2006-07-17 09:36:52 UTC (rev 17083)
+++ branches/SAMBA_4_0/source/smb_server/smb2/smb2_server.h 2006-07-17 09:44:13 UTC (rev 17084)
@@ -53,6 +53,9 @@
/* for matching request and reply */
uint64_t seqnum;
+ /* the id that can be used to cancel the request */
+ uint32_t pending_id;
+
struct smb2_request_buffer in;
struct smb2_request_buffer out;
};
@@ -127,7 +130,13 @@
*/
#define SMB2SRV_CALL_NTVFS_BACKEND(cmd) do { \
req->ntvfs->async_states->status = cmd; \
- if (!(req->ntvfs->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+ if (req->ntvfs->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
+ NTSTATUS _status; \
+ _status = smb2srv_queue_pending(req); \
+ if (!NT_STATUS_IS_OK(_status)) { \
+ ntvfs_cancel(req->ntvfs); \
+ } \
+ } else { \
req->ntvfs->async_states->send_fn(req->ntvfs); \
} \
} while (0)
Modified: branches/SAMBA_4_0/source/smb_server/smb_server.h
===================================================================
--- branches/SAMBA_4_0/source/smb_server/smb_server.h 2006-07-17 09:36:52 UTC (rev 17083)
+++ branches/SAMBA_4_0/source/smb_server/smb_server.h 2006-07-17 09:44:13 UTC (rev 17084)
@@ -324,9 +324,26 @@
/*
* the server_context holds a linked list of pending requests,
* this is used for finding the request structures on ntcancel requests
+ * For SMB only
*/
struct smbsrv_request *requests;
+ /*
+ * the server_context holds a linked list of pending requests,
+ * and an idtree for finding the request structures on SMB2 Cancel
+ * For SMB2 only
+ */
+ struct {
+ /* an id tree used to allocate ids */
+ struct idr_context *idtree_req;
+
+ /* this is the limit of pending requests values for this connection */
+ uint32_t idtree_limit;
+
+ /* list of open tree connects */
+ struct smb2srv_request *list;
+ } requests2;
+
struct smb_signing_context signing;
struct stream_connection *connection;
More information about the samba-cvs
mailing list