Author: metze
Date: 2006-07-17 09:36:52 +0000 (Mon, 17 Jul 2006)
New Revision: 17083

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17083

Log:
- implement SMB2 Cancel in the client
- the 0xffffffffffffffff seqnum is reserved for SMB2 Break (oplock breaks)
  so don't use it in a request. we should someday try to test this...

metze
Added:
   branches/SAMBA_4_0/source/libcli/smb2/cancel.c
Modified:
   branches/SAMBA_4_0/source/libcli/smb2/config.mk
   branches/SAMBA_4_0/source/libcli/smb2/request.c
   branches/SAMBA_4_0/source/libcli/smb2/smb2.h
   branches/SAMBA_4_0/source/libcli/smb2/transport.c


Changeset:
Added: branches/SAMBA_4_0/source/libcli/smb2/cancel.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/smb2/cancel.c      2006-07-17 08:05:02 UTC 
(rev 17082)
+++ branches/SAMBA_4_0/source/libcli/smb2/cancel.c      2006-07-17 09:36:52 UTC 
(rev 17083)
@@ -0,0 +1,78 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   SMB2 client notify calls
+
+   Copyright (C) Stefan Metzmacher 2006
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+
+/*
+  send a cancel request
+*/
+NTSTATUS smb2_cancel(struct smb2_request *r)
+{
+       NTSTATUS status;
+       struct smb2_request *c;
+       uint32_t old_timeout;
+       uint64_t old_seqnum;
+
+       /* 
+        * if we don't get a pending id yet, we just
+        * mark the request for pending, so that we directly
+        * send the cancel after getting the pending id
+        */
+       if (!r->cancel.can_cancel) {
+               r->cancel.do_cancel++;
+               return NT_STATUS_OK;
+       }
+
+       /* we don't want a seqmun for a SMB2 Cancel */
+       old_seqnum = r->transport->seqnum;
+       c = smb2_request_init(r->transport, SMB2_OP_CANCEL, 0x04, False, 0);
+       r->transport->seqnum = old_seqnum;
+       NT_STATUS_HAVE_NO_MEMORY(c);
+       c->seqnum = 0;
+
+       SIVAL(c->out.hdr, SMB2_HDR_FLAGS,       0x00000002);
+       SSVAL(c->out.hdr, SMB2_HDR_UNKNOWN1,    0x0030);
+       SIVAL(c->out.hdr, SMB2_HDR_PID,         r->cancel.pending_id);
+       SBVAL(c->out.hdr, SMB2_HDR_SEQNUM,      c->seqnum);
+       if (r->session) {
+               SBVAL(c->out.hdr, SMB2_HDR_UID, r->session->uid);
+       }
+
+       SSVAL(c->out.body, 0x02, 0);
+
+       old_timeout = c->transport->options.timeout;
+       c->transport->options.timeout = 0;
+       smb2_transport_send(c);
+       c->transport->options.timeout = old_timeout;
+
+       if (c->state == SMB2_REQUEST_ERROR) {
+               status = c->status;
+       } else {
+               status = NT_STATUS_OK;
+       }
+
+       talloc_free(c);
+       return status;
+}

Modified: branches/SAMBA_4_0/source/libcli/smb2/config.mk
===================================================================
--- branches/SAMBA_4_0/source/libcli/smb2/config.mk     2006-07-17 08:05:02 UTC 
(rev 17082)
+++ branches/SAMBA_4_0/source/libcli/smb2/config.mk     2006-07-17 09:36:52 UTC 
(rev 17083)
@@ -20,5 +20,6 @@
        flush.o \
        lock.o \
        notify.o \
+       cancel.o \
        keepalive.o
 PUBLIC_DEPENDENCIES = LIBCLI_RAW LIBPACKET gensec

Modified: branches/SAMBA_4_0/source/libcli/smb2/request.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/smb2/request.c     2006-07-17 08:05:02 UTC 
(rev 17082)
+++ branches/SAMBA_4_0/source/libcli/smb2/request.c     2006-07-17 09:36:52 UTC 
(rev 17083)
@@ -35,6 +35,7 @@
                                       uint32_t body_dynamic_size)
 {
        struct smb2_request *req;
+       uint64_t seqnum;
 
        if (body_dynamic_present) {
                if (body_dynamic_size == 0) {
@@ -47,17 +48,23 @@
        req = talloc(transport, struct smb2_request);
        if (req == NULL) return NULL;
 
+       seqnum = transport->seqnum++;
+       if (seqnum == UINT64_MAX) {
+               seqnum = transport->seqnum++;
+       }
+
        req->state     = SMB2_REQUEST_INIT;
        req->transport = transport;
        req->session   = NULL;
        req->tree      = NULL;
-       req->seqnum    = transport->seqnum++;
+       req->seqnum    = seqnum;
        req->status    = NT_STATUS_OK;
        req->async.fn  = NULL;
        req->next = req->prev = NULL;
 
+       ZERO_STRUCT(req->cancel);
        ZERO_STRUCT(req->in);
-       
+
        req->out.size      = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size;
 
        req->out.allocated = req->out.size + body_dynamic_size;

Modified: branches/SAMBA_4_0/source/libcli/smb2/smb2.h
===================================================================
--- branches/SAMBA_4_0/source/libcli/smb2/smb2.h        2006-07-17 08:05:02 UTC 
(rev 17082)
+++ branches/SAMBA_4_0/source/libcli/smb2/smb2.h        2006-07-17 09:36:52 UTC 
(rev 17083)
@@ -128,6 +128,12 @@
 
        uint64_t seqnum;
 
+       struct {
+               BOOL do_cancel;
+               BOOL can_cancel;
+               uint32_t pending_id;
+       } cancel;
+
        /* the NT status for this request. Set by packet receive code
           or code detecting error. */
        NTSTATUS status;

Modified: branches/SAMBA_4_0/source/libcli/smb2/transport.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/smb2/transport.c   2006-07-17 08:05:02 UTC 
(rev 17082)
+++ branches/SAMBA_4_0/source/libcli/smb2/transport.c   2006-07-17 09:36:52 UTC 
(rev 17083)
@@ -152,8 +152,10 @@
        int len;
        struct smb2_request *req = NULL;
        uint64_t seqnum;
+       uint32_t flags;
        uint16_t buffer_code;
        uint32_t dynamic_size;
+       uint32_t i;
 
        buffer = blob.data;
        len = blob.length;
@@ -165,7 +167,8 @@
                goto error;
        }
 
-       seqnum = BVAL(hdr, SMB2_HDR_SEQNUM);
+       flags   = IVAL(hdr, SMB2_HDR_FLAGS);
+       seqnum  = BVAL(hdr, SMB2_HDR_SEQNUM);
 
        /* match the incoming request against the list of pending requests */
        for (req=transport->pending_recv; req; req=req->next) {
@@ -190,8 +193,13 @@
        req->status       = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
 
        if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) {
-               /* the server has helpfully told us that this request is still 
being
-                  processed. how useful :) */
+               if (flags & 0x00000002) {
+                       req->cancel.can_cancel = True;
+                       req->cancel.pending_id = IVAL(hdr, SMB2_HDR_PID);
+                       for (i=0; i< req->cancel.do_cancel; i++) {
+                               smb2_cancel(req);
+                       }
+               }
                talloc_free(buffer);
                return NT_STATUS_OK;
        }

Reply via email to