Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test
[kai/samba.git] / source3 / smbd / notify.c
index 872ec866446d902f313c5d375712c3a45a5944cb..72872108029b5e1a4acac15a88ac1ad524a202d5 100644 (file)
@@ -24,7 +24,7 @@
 struct notify_change_request {
        struct notify_change_request *prev, *next;
        struct files_struct *fsp;       /* backpointer for cancel by mid */
-       char request_buf[smb_size];
+       uint8 request_buf[smb_size];
        uint32 filter;
        uint32 max_param;
        struct notify_mid_map *mid_map;
@@ -46,7 +46,7 @@ struct notify_mid_map {
        uint16 mid;
 };
 
-static BOOL notify_change_record_identical(struct notify_change *c1,
+static bool notify_change_record_identical(struct notify_change *c1,
                                        struct notify_change *c2)
 {
        /* Note this is deliberately case sensitive. */
@@ -57,7 +57,7 @@ static BOOL notify_change_record_identical(struct notify_change *c1,
        return False;
 }
 
-static BOOL notify_marshall_changes(int num_changes,
+static bool notify_marshall_changes(int num_changes,
                                uint32 max_offset,
                                struct notify_change *changes,
                                prs_struct *ps)
@@ -128,14 +128,14 @@ static BOOL notify_marshall_changes(int num_changes,
  Setup the common parts of the return packet and send it.
 *****************************************************************************/
 
-static void change_notify_reply_packet(const char *request_buf,
+static void change_notify_reply_packet(connection_struct *conn,
+                               const uint8 *request_buf,
                                       NTSTATUS error_code)
 {
-       const char *inbuf = request_buf;
        char outbuf[smb_size+38];
 
        memset(outbuf, '\0', sizeof(outbuf));
-       construct_reply_common(request_buf, outbuf);
+       construct_reply_common((char *)request_buf, outbuf);
 
        ERROR_NT(error_code);
 
@@ -143,27 +143,31 @@ static void change_notify_reply_packet(const char *request_buf,
         * Seems NT needs a transact command with an error code
         * in it. This is a longer packet than a simple error.
         */
-       set_message(inbuf,outbuf,18,0,False);
+       srv_set_message(outbuf,18,0,False);
 
        show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(),outbuf))
-               exit_server_cleanly("change_notify_reply_packet: send_smb "
+       if (!srv_send_smb(smbd_server_fd(),
+                       outbuf,
+                       IS_CONN_ENCRYPTED(conn)))
+               exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
                                    "failed.");
 }
 
-void change_notify_reply(const char *request_buf, uint32 max_param,
+void change_notify_reply(connection_struct *conn,
+                       const uint8 *request_buf, uint32 max_param,
                         struct notify_change_buf *notify_buf)
 {
-       char *outbuf = NULL;
        prs_struct ps;
-       size_t buflen;
+       struct smb_request *req = NULL;
+       uint8 tmp_request[smb_size];
 
        if (notify_buf->num_changes == -1) {
-               change_notify_reply_packet(request_buf, NT_STATUS_OK);
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
+               notify_buf->num_changes = 0;
                return;
        }
 
-       prs_init(&ps, 0, NULL, False);
+       prs_init(&ps, 0, NULL, MARSHALL);
 
        if (!notify_marshall_changes(notify_buf->num_changes, max_param,
                                        notify_buf->changes, &ps)) {
@@ -171,26 +175,31 @@ void change_notify_reply(const char *request_buf, uint32 max_param,
                 * We exceed what the client is willing to accept. Send
                 * nothing.
                 */
-               change_notify_reply_packet(request_buf, NT_STATUS_OK);
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
                goto done;
        }
 
-       buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */;
-
-       if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
-               change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+       if (!(req = talloc(talloc_tos(), struct smb_request))) {
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY);
                goto done;
        }
 
-       construct_reply_common(request_buf, outbuf);
+       memcpy(tmp_request, request_buf, smb_size);
 
-       if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
-                           prs_offset(&ps), NULL, 0) == -1) {
-               exit_server("change_notify_reply_packet: send_smb failed.");
-       }
+       /*
+        * We're only interested in the header fields here
+        */
+
+       smb_setlen((char *)tmp_request, smb_size);
+       SCVAL(tmp_request, smb_wct, 0);
+
+       init_smb_request(req, tmp_request,0, conn->encrypted_tid);
+
+       send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
+                       prs_offset(&ps), NULL, 0);
 
  done:
-       SAFE_FREE(outbuf);
+       TALLOC_FREE(req);
        prs_mem_free(&ps);
 
        TALLOC_FREE(notify_buf->changes);
@@ -205,7 +214,7 @@ static void notify_callback(void *private_data, const struct notify_event *e)
 }
 
 NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
-                             BOOL recursive)
+                             bool recursive)
 {
        char *fullpath;
        struct notify_entry e;
@@ -237,9 +246,10 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
        return status;
 }
 
-NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param,
-                                  uint32 filter, BOOL recursive,
-                                  struct files_struct *fsp)
+NTSTATUS change_notify_add_request(const struct smb_request *req,
+                               uint32 max_param,
+                               uint32 filter, bool recursive,
+                               struct files_struct *fsp)
 {
        struct notify_change_request *request = NULL;
        struct notify_mid_map *map = NULL;
@@ -253,7 +263,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param,
        request->mid_map = map;
        map->req = request;
 
-       memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
+       memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf));
        request->max_param = max_param;
        request->filter = filter;
        request->fsp = fsp;
@@ -262,11 +272,11 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param,
        DLIST_ADD_END(fsp->notify->requests, request,
                      struct notify_change_request *);
 
-       map->mid = SVAL(inbuf, smb_mid);
+       map->mid = SVAL(req->inbuf, smb_mid);
        DLIST_ADD(notify_changes_by_mid, map);
 
        /* Push the MID of this packet on the signing queue. */
-       srv_defer_sign_response(SVAL(inbuf,smb_mid));
+       srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
 
        return NT_STATUS_OK;
 }
@@ -319,7 +329,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid)
                return;
        }
 
-       change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED);
+       change_notify_reply_packet(map->req->fsp->conn,
+                       map->req->request_buf, NT_STATUS_CANCELLED);
        change_notify_remove_request(map->req);
 }
 
@@ -335,7 +346,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
        }
 
        while (fsp->notify->requests != NULL) {
-               change_notify_reply_packet(
+               change_notify_reply_packet(fsp->conn,
                        fsp->notify->requests->request_buf, status);
                change_notify_remove_request(fsp->notify->requests);
        }
@@ -429,7 +440,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
         * TODO: do we have to walk the lists of requests pending?
         */
 
-       change_notify_reply(fsp->notify->requests->request_buf,
+       change_notify_reply(fsp->conn,
+                       fsp->notify->requests->request_buf,
                            fsp->notify->requests->max_param,
                            fsp->notify);